AOP是一种思想,一种面向切面的变成思想,可以无侵入的增加一些额外的逻辑。提到AOP就会想到动态代理,关于动态代理的应用场景和实现方式(JDK和CGLIB)不是本章重点,大家不熟悉的自行百度,今天我们的主题是Spring的AOP功能,关于AOP涉及到的切面、切点等一大堆我不想一开始就长篇大论抛出来,我会顺着源码的脉络提出来。
我们知道,Spring是项目运行所需实例(Bean)的一个大管家,它会在容器启动的时候帮我们把所需的类都创建好,使用的时候只需注入就ok了,那么AOP是在什么时候做的呢——它在被代理对象创建完成(实例化)之后才会生成代理对象,因为有了源对象,才能生成代理对象,进行业务增强。
接下来进入源码,在Bean实例化的核心方法doCreateBean()方法org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// BeanWrapper是实例化之后的对象又做了封装
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// TODO 创建实例,重点看
// 1.实例化factoryMethod方法对应的实例
// 2.实例化带有@Autowired注解的有参构造函数
// 3.实例化没有@Autowired注解的有参构造函数
// 4.实例化无参构造函数
// 实例化之后堆内存中有了该实例,但是属性却是空的(一个不完整的对象)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 从BeanWrapper中拿真正的实例对象
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
/**
* TODO CommonAnnotationBeanPostProcessor支持@PostConstruct、@PreDestroy、@Resource注解
* AutowiredAnnotationBeanPostProcessor支持@Autowired、@Value注解
* 收集注解:对类中注解的装配过程
* 这个方法是BeanPostProcessor接口的典型运用, 重要程度5,必须看
* 收集类中有注解的属性和方法,包装成对象,并将对象加入到容器,并把容器包装成InjectionMetadata对象,并放到缓存中
* 缓存是beanName和InjectionMetadata的对应关系,然后通过这个对象可以知道,哪个属性或方法上有注解,为下面的填充做准备
*/
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// TODO 添加三级缓存,即执行getEarlyBeanReference(),这里着重理解,助于理解循环依赖,
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
/**
* TODO IOC、DI,依赖注入的核心方法,重要程度:5,
* 主要是完成@Autowired、@Resource、xml配置方式的依赖注入
* 在此之前,堆内存已经有实例,只是属性为空,所以这个方法做的就是属性填充
*/
populateBean(beanName, mbd, instanceWrapper);
/**
* TODO Bean实例化+IOC依赖注入完成之后的调用,重要程度:5
* init-method属性和initializingBean接口方法afterPropertiesSet()调用,@PostConstruct注解方法调用,以及AOP代理对象的生成入口
*/
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
----省略无关代码----
}
完成beanDefinition的属性填充之后,进入initializeBean()方法:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 调用Aware接口方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 对类中某些特殊方法的调用,比如@PostConstruct,Aware接口,非常重要 重要程度: 5
// 类似于装饰,如果有需要,在这里将需要操作的bean各种操作后再返回,也可以原封不动返回
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用实现了InitializingBean接口的afterPropertiesSet(),init-method属性调用,非常重要,重要程度:5
// InitializingBean接口的afterPropertiesSet()是在bean实例化之后调用
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 和上面的applyBeanPostProcessorsBeforeInitialization()类似,都是BeanPostProcessor的应用
// 这个地方会生成代理实例,AOP的入口,AOP的实现也是通过埋点来生成的
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
AOP的入口是在Bean实例化的末尾, 通过BeanPostProcessor 的埋点postProcessAfterInitialization()方法里面进行的:
// AOP的入口
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
// 一些validate的框架都是在这调用的
// 被@Component注解修饰的事件监听在ApplicationListenerDetector中加入到Spring容器中
// AOP的埋点入口->进入AbstractAutoProxyCreator.postProcessAfterInitialization()方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
当我们通过@EnableAspectJAutoProxy开启AOP功能时,getBeanPostProcessors()方法获取到的BeanPostProcessor类就会多一个AnnotationAwareAspectJAutoProxyCreator。我们先进入它的父类AbstractAutoProxyCreator.postProcessAfterInitialization()方法:
所属类:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
/**
* TODO 生成当前实例化bean的代理
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 生成代理的逻辑
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
我们先看xml标签中AOP功能的实现,它涉及到自定义标签的解析,XML中开启AOP功能,必须要有<aop:aspectj-autoproxy>标签。
进入META-INF目录下的spring-handlers文件:
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
进入AopNamespaceHandler类:
public class AopNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// In 2.0 XSD as well as in 2.5+ XSDs
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// AOP对应的标签是这个,它的解析由AspectJAutoProxyBeanDefinitionParser类负责
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
进入AspectJAutoProxyBeanDefinitionParser类:
// 标签的解析方法
public BeanDefinition parse(Element element, ParserContext parserContext) {
// TODO 核心方法
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
进入registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法:
所属类:org.springframework.aop.config.AopConfigUtils
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注册生成AOP代理类的AutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
进入registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 把AnnotationAwareAspectJAutoProxyCreator(是AbstractAutoProxyCreator的子类)变成BeanDefinition,让Spring进行管理
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
也是BeanPostProcessor调用的时候,把AnnotationAwareAspectJAutoProxyCreator(AOP的入口类)这个Bean注册到Spring容器,它会去解析@Aspect注解类中定义的切面,创建代理对象,我们会在后面的源码中看到。
看一下AnnotationAwareAspectJAutoProxyCreator的结构,它继承自AspectJAwareAdvisorAutoProxyCreator,AspectJAwareAdvisorAutoProxyCreator又继承了AbstractAdvisorAutoProxyCreator抽象类,它的父类是AbstractAutoProxyCreator 。我们重点介绍一下这两个类:
AbstractAdvisorAutoProxyCreator
AbstractAdvisorAutoProxyCreator非常强大以及重要,Spring容器中如果存在这个类型的
Bean,就相当于开启了AOP。AbstractAdvisorAutoProxyCreator实际上就是一个
BeanPostProcessor,在创建某个Bean时,就会进入到对应的方法,比如:在某个Bean初始化之后,会调用wrapIfNecessary()方法进行AOP,底层逻辑是:
AbstractAdvisorAutoProxyCreator会找到所有的Advisor,然后判断当前的Bean是否存在某个
Advisor与之匹配(根据Pointcut),如果匹配就表示当前这个Bean有对应的切面逻辑,需要进行
AOP,需要产生一个代理对象。另外,Spring事务InfrastructureAdvisorAutoProxyCreator也是通过继承该类实现的。
AbstractAutoProxyCreator
AbstractAutoProxyCreator 继承ProxyProcessorSupport实现了SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware接口。
SmartInstantiationAwareBeanPostProcessor又实现了InstantiationAwareBeanPostProcessor接口,实现了InstantiationAwareBeanPostProcessor的接口会在容器初始化完成以后执行before和after方法,BeanFactoryAware接口的子类可以拿到spring的 BeanFactory的,也就是所有bean的对象。
AbstractAutoProxyCreator 里面有上面我们看到的生成AOP的逻辑postProcessAfterInitialization()方法。如果想实现自定义的代理逻辑,可以继承该抽象类,Seta中@GlobalTransactional注解就是。
另外,我们用注解@EnableAspectJAutoProxy开启AOP功能,和<aop:aspectj-autoproxy>标签的作用类似,它会在Spring的容器中注册一个组件,相当于@Import(AnnotationAwareAspectJAutoProxyCreator.class),通过AspectJAutoProxyRegistrar类,将代理入口类AnnotationAwareAspectJAutoProxyCreator实例化,才会有这个入口类,看一下该注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
如果某个功能想通过注解导入进来,可以通过@Import注解,实现ImportBeanDefinitionRegistrar接口:
// 重写该方法
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 把AOP的入口类实例化,通过registerAspectJAnnotationAutoProxyCreatorIfNecessary方法变成BeanDefinition
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
也是通过AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)方法把变AnnotationAwareAspectJAutoProxyCreator成BeanDefinition,和自定义标签解析殊途同归。
回到AbstractAutoProxyCreator类的postProcessAfterInitialization()方法:
/**
* TODO 生成当前实例化bean的代理
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// earlyProxyReferences是一个ConcurrentHashMap,里面存放的是已经生成的代理
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 生成当前实例化bean的代理对象**
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
这个earlyProxyReferences是一个ConcurrentHashMap<>(16),里面存放的是已经生成的代理(三级缓存可能会提前生成代理),如果有不会重复生成。
Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
如果没有,就会进入下面的wrapIfNeseessary()方法,该方法里面包含了真正生成代理对象的逻辑。这个入口,是为了给普通bean能够生成代理用的,是spring最常见并且使用最多的入口。
下面我们着重看一下wrapIfNecessary()方法:
所属类:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// advicedBeans表示已经判断过的bean,false表示此Bean不需要进行AOP,直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 当前正在创建的Bean不用进行AOP,比如切面Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 找切面的过程(判断当前实例化的bean是否有切面,如果有则将切面返回)*****
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果有切面,则生成bean的代理
if (specificInterceptors != DO_NOT_PROXY) {
// advisedBeans记录了某个Bean已经进行过AOP了
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理,把被代理对象bean的实例封装到SingletonTargetSource中,生成当前实例化bean的代理对象*****
// 传入的bean是被代理实例,SingletonTargetSource持有了被代理实例的引用(一级缓存单例池中存的就是代理对象)
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
// 将代理对象返回
return proxy;
}
// 没有代理的情况,就是false
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
上面方法参数中的bean就是正在实例化的Bean,它是从AOP的入口类中传过来的,如果需要被代理,就对它进行包装(代理)。另外,多说一句,一级缓存singletonObjects单例池中存的就是代理对象。
上面这个方法主要做了两件事:1.找切面;2.创建代理,本章先看第一个:
找切面:
切面是什么:一类功能的增强,如:日志功能、事务功能、缓存功能,spring中切面封装类为Advisor,必须要有PointCut(对什么类起作用)和Advice(起什么作用),在Spring实例化的过程中,为了便于理解,我们可以把它一种特殊的Bean。
PointCut:又叫切点,作用是匹配、拦截,一般为@Pointcut注解的方法;
Advice:增强,具体增强的代码(承载了一些增强的逻辑),如带有@Around、@Before、@After注解的方法。
举例:
@Aspect
public class SysLogAspect {
/**
* Pointcut:作用范围,凡是带有@LogAnnotation注解的方法都进行增强
*/
@Pointcut("@annotation(cn.baec.common.aop.annotation.LogAnnotation)")
public void logPointCut() {
}
/**
* Advice:如何增强,方法执行时增加日志打印功能
*/
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
// 执行方法
Object result = point.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
// 记录日志
try {
printSysLog(point, result, time);
} catch (Exception e) {
log.error("接口异常信息:{}", e);
}
return result;
}
进入子类的getAdvicesAndAdvisorsForBean()方法看找切面的逻辑:
所属类:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 找到合格的切面***
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到候选的切面,就是寻找带有@Aspect注解的过程,把带有@Aspect的类封装成Advisor返回
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 判断候选的切面是否作用在当前beanClass上面,就是一个匹配的过程
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 针对有@Aspect注解的类添加一个默认的切面--->DefaultPointcutAdvisor,解决参数传递问题
// 进入AspectJAwareAdvisorAutoProxyCreator类的extendAdvisors()方法
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 对有@Order、@Priority注解的类进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
上面的方法分两步:第一,找候选切面;第二,匹配(拦截类和方法),Pointcut的作用就是匹配、拦截,所以一定会有ClassFilter(拦截类),MethodMather(匹配方法)这两个元素。
一、先看本类的findAdvisorBeans()方法,寻找带有@Aspect注解的类,找到候选切面,封装成Advisor:
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
进入findAdvisorBeans()方法:
所属类:org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// 找到所有实现Advisor接口的类的名称,可以实现Advisor接口实现自定义切面
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
// 然后根据名称找到类加入容器
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
----省略无关代码----
如果是通过@Aspect注解开启切面,会进入到AbstractAdvisorAutoProxyCreator的子类AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors()方法:
所属类:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
// 找到候选的切面,就是寻找有@Aspect注解的过程,封装成Advisor返回
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 先找到所有Advisor类型的Bean
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 再从所有切面中解析得到Advisor对象
if (this.aspectJAdvisorsBuilder != null) {
// 创建候选的切面,对有@Aspect注解的类进行处理(包装Advice和Pointcut,还有切面的排序)****
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
进入核心方法buildAspectJAdvisors()创建切面Advisor对象:
所属类:org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 获取Spring容器中所有实例的beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
// 首先拿到实例的类型
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 判断类上是否有@Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
// 获取切面的注解信息
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 创建获取@Aspect注解类的实例工厂,MetadataAwareAspectInstanceFactory负责获取有@Aspect注解的实例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// 创建切面Advisor对象***
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
// 放到缓存中
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
----省略无关代码----
进入创建切面Advisor对象getAdvisors(factory)方法:
所属类:org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 从工厂中获取有@Aspect注解的类的反射对象Class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 从工厂中获取有@Aspect注解的类的名称
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
// 创建工厂的装饰类,获取实例(只会获取一次)
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 这里循环没有@Pointcut注解的方法,扫描有@Before、@Around、@After注解的方法,并进行排序,getAdvisorMethods()->
for (Method method : getAdvisorMethods(aspectClass)) {
// 获取Advisor*****(只要是有@Before、@After等注解的方法,它们分别和带有@Pointcut注解的方法组合,生成各自Advisor类)
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
// 判断属性上是否有引介注解
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
先进入本类的getAdvisorMethods()方法:
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
// 排除有@Pointcut注解的方法
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
// methods就是存放没有@Pointcut注解的方法
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
// 按照注解先后顺序+自然顺序排序
methods.sort(METHOD_COMPARATOR);
}
return methods;
}
再进入本类的getAdvisor(),根据方法生成Advisor:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
// 获取AspectJExpressionPointcut对象,从注解中获取表达式
// candidateAdviceMethod就是有@Before、@After注解的方法
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 创建真正的Advisor切面类,里面有pointcut和advice***进入InstantiationModelAwarePointcutAdvisorImpl的构造方法
// expressionPointcut是pointcut,candidateAdviceMethod是advice
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
创建真正的切面类是在InstantiationModelAwarePointcutAdvisorImpl的构造方法中,该类实现了InstantiationModelAwarePointcutAdvisor接口,每个Advisor会返回一个InstantiationModelAwarePointcutAdvisorImpl实例。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
----省略无关代码----
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 创建advice对象***
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
进入instantiateAdvice()方法:
所属类:springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
// 创建Advice对象,调用到ReflectiveAspectJAdvisorFactory.getAdvice()方法
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
创建Advisor切面类,必须要有PointCut(对什么类起作用)和Advice(起什么作用)这两个角色,比如:
@Test
public void testSpringProxy() {
GoodsService target = new GoodsService();
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(target);
proxyFactory.addAdvisor(new PointcutAdvisor() {
@Override
public Pointcut getPointcut() {
return new StaticMethodMatcherPointcut() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().equals("test");
}
};
}
@Override
public Advice getAdvice() {
// 导org.aopalliance.intercept.MethodInterceptor
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("before...");
// 执行被代理方法
Object result = invocation.proceed();
System.out.println("after...");
return result;
}
};
}
@Override
public boolean isPerInstance() {
return false;
}
});
// 动态代理所创建出来的UserService对象
GoodsService goodsService = (GoodsService) proxyFactory.getProxy();
// 执行这个userService的test方法时,就会额外会执行一些其他逻辑
goodsService.test();
}
代理对象在执行时先调用Advisor接口实例的getAdvice()方法:
所属类:springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
然后,会调用到instantiateAdvice(),InstantiationModelAwarePointcutAdvisorImpl类的构造方法else分支中的instantiateAdvice()方法:
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
// 创建Advice对象,调用到ReflectiveAspectJAdvisorFactory.getAdvice()方法
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
接下来,会解析创建来的Method上面有哪种类型的注解,创建对应的Advice:
所属类:org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory
// 获取Advice方法***(candidateAdviceMethod是有注解的方法)
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// 获取有@Aspect注解的类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 找到candidateAdviceMethod方法上面的注解,并且包装成AspectJAnnotation对象
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
// 根据不同的注解类型创建不同的advice实例***
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
// 环绕通知,实现了MethodInterceptor接口
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
// 前置通知,实现了MethodBeforeAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
// 后置通知,实现了MethodInterceptor接口
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
// 结果通知,实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
// 异常通知,实现了MethodInterceptor接口
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}
// 计算argNames和类型的对应关系
springAdvice.calculateArgumentBindings();
return springAdvice;
}
在这里,五种不同的通知都实现了Advice接口,但是有些差异,AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice实现了MethodInterceptor接口:
另外两个类:AspectJMethodbeforeAdvice和AspectJAfterReturningAdvice没有实现上面的接口,它们俩继承了AbstractAspectJAdvice抽象类。
以AspectJMethodBeforeAdvice类为例,进去看一下:
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
/**
* @param aspectJBeforeAdviceMethod 有@Before注解的Method对象
* @param pointcut @Before所对应的Pointcut,表示当前Advice所对应的切点
* @param aif
*/
public AspectJMethodBeforeAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
// 代理对象执行时就会执行该方法
@Override
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
@Override
public boolean isBeforeAdvice() {
return true;
}
@Override
public boolean isAfterAdvice() {
return false;
}
}
进入invokeAdviceMethod()方法:
protected Object invokeAdviceMethod(
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
throws Throwable {
// 进入invokeAdviceMethodWithGivenArgs()方法
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
// aspectJAdviceMethod是@Before修饰的方法
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
actualArgs = null;
}
try {
// 反射调用aspectJAdviceMethod方法
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
// this.aspectInstanceFactory.getAspectInstance()指切面Bean的实例,actualArgs为方法参数,执行对应方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
需要注意的是,MethodInterceptor接口中有invoke()方法,切面功能增强的代码会调到下面,以@Around注解的解析类AspectJAroundAdvice为例,它实现了MethodInterceptor接口,我们进去看一下:
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
----省略无关代码----
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
}
最终增强的逻辑就是invoke()方法,到此,找候选切面类的过程完成,简单总结一下这个过程:
1. 自定义类实现Advisor接口,并且在类中定义自己的Pointcut和Advice;
2. 解析有@Aspect注解的类,解析有@Before、@After等注解的方法,创建Advice对象,通过注解中配置的value值,创建Pointcut对象,最终根据创建的Advice和Pintcut对象,创建Advisor对象。
找到Advisor切面类,回到AbstractAdvisorAutoProxyCreator的findEligibleAdvisors()方法,进入匹配过程,判断候选的切面是否作用在当前beanClass上面;
二、进入findAdvisorsThatCanApply()方法:
所属类:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 看看当前类是否在这些切面的Pointcut中,调用类和方法的match()过程,找到后返回切面
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
进入findAdvisorsThatCanApply()方法:
所属类:org.springframework.aop.support.AopUtils
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
// 如果是引介切面并且匹配
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
// 类匹配和方法匹配(调用pointcut中的ClassFilter和MethodMatcher的match()的过程)
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// Advisor和当前的Bean进行匹配****进入canApply()方法->
if (canApply(candidate, clazz, hasIntroductions)) {
// 匹配成功,将切面Advisor返回
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
// 引介的情况
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
// 会进入这里,调用下面的canApply()方法***
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
// 获取表达式匹配类和方法,返回true表示当前实例化的bean和advisor是匹配的,也就是这个bean有切面
// pca.getPointcut()方法表示从PointcutAdvisor拿到Pointcut实例
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
在spring中,通过表达式
@Pointcut("execution(public * com.kieasar.cache.service.TestService.*(..))")
具体匹配某个类,execution
只是其中一种,还有:
所以,除了类匹配之外,还需要方法匹配,所以需要先匹配类,再匹配方法。 进入canApply()方法,pc就是Advisor中的Pointcut,如果两个都能匹配则返回true, 表示切面拦截到了这个类,这个类有切面。自定义的Pointcut的matches()就是在这里执行 。
所属类:org.springframework.aop.support.AopUtils
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 调用classFilter的matches()方法,判断targetClass是否和当前Pointcut匹配,
// 调用aop.aspectj.AspectJExpressionPointcut.matches(java.lang.Class<?>)方法**
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
// 判断类中方法是否匹配,有些可能是方法上面有注解的拦截,所以需要判断方法是否匹配
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
// 方法匹配
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
进入AspectJExpressionPointcut类的matches(java.lang.Class<?>)方法,看具体的匹配过程:
public boolean matches(Class<?> targetClass) {
// 根据@Around("pc()")配置中的pc找到@Pointcu注解对应的方法,从而找到Pointcut表达式
PointcutExpression pointcutExpression = obtainPointcutExpression();
try {
try {
// 根据表达式匹配类,看目标类是否在表达中包含的范围
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
if (fallbackExpression != null) {
return fallbackExpression.couldMatchJoinPointsInType(targetClass);
}
}
}
catch (Throwable ex) {
logger.debug("PointcutExpression matching rejected target class", ex);
}
return false;
}
三、进入extendAdvisors()方法:
所属类:org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
// 对有@Aspect注解的类添加默认的切面DefaultPointcutAdvisor
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
进入makeAdvisorChainAspectJCapableIfNecessary()方法:
所属类:org.springframework.aop.aspectj.AspectJProxyUtils
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
// 判断是否为带有@Aspect注解的类
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
// 判断是否包含默认的切面类DefaultPointcutAdvisor,ExposeInvocationInterceptor包括了链式调用的逻辑(利用了threadLocal)
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
// 如果不包含就在Advisor集合的第一个位置添加DefaultPointcutAdvisor元素
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
我们看一下 ExposeInvocationInterceptor类,它实现了MethodInterceptor接口,在该类中实现了链式调用的逻辑,通过threadLocal来维护AOP调用链中的MethodInvocation 对象,我们也可以通过该工具类获取调用的入参、方法、对象等信息。
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
/** Singleton instance of this class. */
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
/**
* Singleton advisor for this class. Use in preference to INSTANCE when using
* Spring AOP, as it prevents the need to create a new Advisor to wrap the instance.
*/
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@Override
public String toString() {
return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
}
};
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
/**
* 从threadLocal中获取当前AOP中的MethodInvocation对象
*/
public static MethodInvocation currentInvocation() throws IllegalStateException {
MethodInvocation mi = invocation.get();
if (mi == null) {
throw new IllegalStateException(
"No MethodInvocation found: Check that an AOP invocation is in progress and that the " +
"ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +
"advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! " +
"In addition, ExposeInvocationInterceptor and ExposeInvocationInterceptor.currentInvocation() " +
"must be invoked from the same thread.");
}
return mi;
}
// 用代理对象调用advice,最终会进入这里,把MethodInvocation放到threadLocal中,然后进行火炬传递
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
// 链式调用,火炬传递
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
@Override
public int getOrder() {
return PriorityOrdered.HIGHEST_PRECEDENCE + 1;
}
总结一下上面的过程:
- Bean的实例化;
- 找出所有的切面Bean;
- 遍历切面中的每个方法,看是否写了@Before、@After等注解;
- 如果写了,则判断所对应的Pointcut是否和当前Bean对象的类是否匹配;
- 如果匹配则表示当前Bean对象有匹配的的Pointcut,则通过ProxyFactory生成代理对象。
总之就是,在Bean的实例化完成之后,调用BeanPostProcessor(AbstractAutoProxyCreator实现BeanPostProcessor接口)的postProcessAfterInitialization()方法,检查是否需要生成代理(先找切面,再匹配),现在切面找到了,下一章进入生成代理的环节。