
1.开启AOP
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJ***Registrar.class) public @interface EnableAspectJ*** {
基于AspectJ注解形式开启AOP需要使用@EnableAspectJ***注解,进入这个注解,它通过@Import标签向容器当中导入了一个注册器AspectJ***Registrar。
private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(***_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(***_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(***_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
然后AspectJ***Registrar类实现了ImportBeanDefinitionRegistrar 接口,熟悉IOC容器的话应该能理解实现了在ImportBeanDefinitionRegistrar .registerBeanDefinitions()方法中可以动态的往容器里面添加Bean的配置(BeanDefinition)信息,也就是向BeanFactory中注册AnnotationAwareAspectJ***Creator对象的BeanDefinition信息。

观察继承关系图,因为它是后置处理器,所有在容器启动的Refresh()方法中会执行registerBeanPostProcessors(beanFactory) 方法时候会创建它。


打断点能看到未执行registerBeanPostProcessors方法前BeanDefinitionMap中是存在这个BeanDefinition的。
单例池中和BeanPostProcessors是没有生成这个bean的。

执行该方法后能够看到单例池和BeanPostProcessors中存在了这个后置处理器的Bean。
以上都是IOC的内容。

上图是AnnotationAwareAspectJ***Creator后置处理器的注册和创建阶段的流程图。
到此为止,我们已经知道Refresh()方法中的registerBeanPostProcessors() 方法已经初始化这个Bean了,在singletonObjects(即单例池)中是能看到这个bean的。
那么这个后置处理器是如何操作的呢?
在Refresh()方法中的registerBeanPostProcessors() 后面有一个方法finishBeanFactoryInitialization() ,会初始化所有的单例对象,而后置处理器就是在实例化和初始化这些对象的过程中发挥作用的。
2.切面通知加载
AnnotationAwareAspectJ***Creator的父类实现了InstantiationAwareBeanPostProcessor,而该接口继承了后置处理器BeanPostProcessor接口,他的父类有这么几个实现方法;
//bean实例化前的回调操作 @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { } //bean实例化后的回调操作 @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) { } //bean实例化完成后初始化之前回调操作 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { } //bean实例化完成初始化之后回调操作 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { }

这里提前介绍说明一下:postProcessBeforeInstantiation方法中会加载切面及通知。
SpringIOC的refresh()方法包含了许多逻辑,其中在finishBeanFactoryInitialization()方法中,开始了解析AnnotationAwareAspectJ***Creator的工作。
熟悉一下IOC初始化bean的过程:
preInstantiateSingletons() -----> getBean() -----> doGetBean() ----->getSingleton(尝试从缓存中获取)---->lamda内部类方法getObject----->CreatBean();
在CreatBean方法中有一个方法:resolveBeforeInstantiation(beanName, mbdToUse);
该方法就会遍历所有后置处理器,调用InstantiationAwareBeanPostProcessor类型的后置处理器的postProcessBeforeInstantiation方法。
正好容器中@EnableAspectJ***为我们添加了该类型的后置处理器。所以每次单实例bean创建的时候都会调用该方法。
try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }
会先尝试返回一个代理对象,如果返回不成功,那么就执行doCreatBean方法。
@Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { // 调用AnnotationAwareAspectJ***Creator的postProcessorsBeforeInstantiation() // 其实是父类Abstract***Creator中的 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { //调用AnnotationAwareAspectJ***Creator的postProcessAfterInitialization() bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
在看postProcessBeforeInstantiation()之前先看下我写的切面类,
@Component @Aspect public class Aop { /** * 切面 */ @Pointcut("execution(* com.yang.service..*.*(..))") public void pointcut() { } @Before("pointcut()") public void before() { System.out.println("增强-------------------------------------------"); } }
我的demo中切面类叫AOP,接下来就看postProcessBeforeInitialization()是如何解析@Aspect修饰的类的;
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { //省略代码---------------------------------------- if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
getAdvicesAndAdvisorsForBean方法,该方法的目的是获取并生成Advisor Bean。其中包含了扫描通过@Aspect注解配置且与Bean方法的匹配的Advice。
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) { //获取到所有切面通知方法 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //匹配到符合当前对象的通知方法 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); //特殊处理,这里不赘述 extendAdvisors(eligibleAdvisors); //对通知方法集合进行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
什么是Advisor? 首先,Advice是增强方法,即@Around, @Before等注解修饰的方法。而Advisor则是在Advice之上再包了一层。例如PointcutAdvisor则包有Advice和Pointcut
findCandidateAdvisors()
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
这里findCandidateAdvisors在AbstractAdvisor***Creator中有实现,同时被AnnotationAwareAspectJ***Creator重写了。
不过可以看到重写的方法中先调用了super.findCandidateAdvisor。
this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 从所有Bean中获取@Aspect配置的Bean并创建Advisor,也是我们关注的内容。
由于这段代码比较长,这里就不细说了,深挖的话还能再写一篇文章。
主要是通过beanName扫描@Aspect配置并生成Advisor的过程了。
其中this.advisorFactory.getAdvisors(factory)是生成Advisor类的具体内容。
findAdvisorsThatCanApply()
现在我们获得了所有的候选Advisor,那么找出和当前Bean匹配的Advisor呢?
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
会执行AopUtils.findAdvisorsThatCanApply
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(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
最后定位到canApply()
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }

可以看出判断是否是该bean合适的advisor,是通过advisor.getPointcut().getClassFilter().matches(targetClass)方法来判断的。匹配完class以后下面还有MethodMatcher来匹配method。回想我们在配置pointcut的时候不仅仅有class的规则,也有method的规则。
当然,再深入matches方法进去的话就是pointcut的匹配语法实现了。有兴趣的可以自行阅读。