AOP的实现过程 - 前言 主业务在A类中,辅助业务在切面B类中,在Spring项目的启动过程中,会将A和B类“组合”成一个新的类C,C在执行A的主业务逻辑时,在恰当的时机,会调用B中的方法,C就是代理类。
主业务类A叫做目标类,A中的方法叫做目标方法
辅助业务类B叫做切面 ,切面(@Aspect
)中有切点(@Pointcut
)和通知(@Before、@After、@Around等)
C类叫做代理类
所以,AOP的实现过程有两个阶段:
目标对象是如何变成代理对象的?
代理对象是怎么执行目标方法的?
AOP的实现过程 - 1、目标对象变成代理对象的过程 首先是目标类实例化为目标对象,这个过程是IoC容器初始化、创建bean的过程。
相关方法调用 doCreateBean -> initializeBean 来看一下AbstractAutowireCapableBeanFactory 的doCreateBean 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 protected Object doCreateBean (String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null ; if (mbd.isSingleton()) { instanceWrapper = this .factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null ) { instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); ... Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { } ... }
先有的目标类bean,然后再为其创建代理对象。
initializeBean -> applyBeanPostProcessorsAfterInitialization 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 protected Object initializeBean (String beanName, Object bean, @Nullable RootBeanDefinition mbd) { invokeAwareMethods(beanName, bean); Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null ), beanName, ex.getMessage(), ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } public Object applyBeanPostProcessorsAfterInitialization (Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null ) { return result; } result = current; } return result; }
bean被创建后,会调用所有的BeanPostProcessor 作用在bean上,其中有一个名叫AnnotationAwareAspectJAutoProxyCreator 的BeanPostProcessor,是它将bean变成了对应的代理类 。
AnnotationAwareAspectJAutoProxyCreator类 先看下AnnotationAwareAspectJAutoProxyCreator 的类关系图:
postProcessAfterInitialization -> wrapIfNecessary 接下来看下代理对象是怎么生成的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 public Object postProcessAfterInitialization (Object bean, String beanName) { return bean; } 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; } protected Object wrapIfNecessary (Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this .targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this .advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this .advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null ); if (specificInterceptors != DO_NOT_PROXY) { this .advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this .proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this .advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
wrapIfNecessary 判断有没有针对当前bean的切面。如果没有,直接将bean返回;如果有,为bean创建代理对象。
思考一下问题:
切面信息是怎么拿到的?更确切的说,切面是怎么被解析的
怎么判断有没有针对当前bean的切面?其实找的是有没有作用在当前bean上的通知。
获取切面信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 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; } protected List<Advisor> findCandidateAdvisors () { List<Advisor> advisors = super .findCandidateAdvisors(); if (this .aspectJAdvisorsBuilder != null ) { advisors.addAll(this .aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
切面是怎么被解析的 切面@Aspect
最开始也只是个class文件,只有被注入、解析后才能使用。 大概简述下切面被注入和解析的思路:
切面被注入的过程: 切面类上有@Component
注解,所以在工程启动时ConfigurationClassPostProcessor
会加载切面的class文件,创建对应的BeanDefinition,为其创建对应的bean保存到applicationContext
中的beanFactory
属性的beanDefinitionMap
中,切面就这样被注入了。
解析切面,最终解析到切面的通知上去,因为辅助的aop逻辑都在通知里面 去beanFactory
中拿所有的object的beanName,即获取所有bean的名字,为每一个beanName创建Class对象,判断该Class对象上有没有@Aspect
注解,如果有,那这个类就是切面类。 获取类中的方法,判断类的方法上有没有@Before、@After、@Around等注解,如果有,那这个方法就是通知,为每一个通知创建一个Advisor
对象,将所有的Advisor对象保存到advisors列表中。
解析切面的执行时机 todo
筛选作用于当前bean的增强器 todo
创建代理对象 目标类的bean有了,作用在这个bean上的增强器也找到了,接下来就是拿着这两个东西创建代理对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 protected Object createProxy (Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this .beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this .beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this ); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true ); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this .freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true ); } return proxyFactory.getProxy(getProxyClassLoader()); }
代理工厂返回的是AopProxy 接口,它有两个实现CglibAopProxy 和JdkDynamicAopProxy 。至于创建的到底是哪一个,要根据条件判断的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public Object getProxy (@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } public Class<?> getProxyClass(@Nullable ClassLoader classLoader) { return createAopProxy().getProxyClass(classLoader); } Object getProxy (@Nullable ClassLoader classLoader) ;public AopProxy createAopProxy (AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null ) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation." ); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
AnnotationAwareAspectJAutoProxyCreator是怎么被加载的? 前面写到AnnotationAwareAspectJAutoProxyCreator 解析了切面,创建了增强器,最后将目标对象变成了代理对象,那这个类是怎么被加载到的呢?
1 2 3 4 5 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy {}
@EnableAspectJAutoProxy 注解将AnnotationAwareAspectJAutoProxyCreator的beanDefinition 注入了applicationContext 中。
接下来通过 beanDefinition 创建对应 bean 的过程,AnnotationAwareAspectJAutoProxyCreator的bean 也就注入了applicationConext 中。
AnnotationAwareAspectJAutoProxyCreator 实现了BeanPostProcessor 接口,所以在对目标类的 bean 执行初始化时,会调用所有的 BeanPostProcessor,当然少不了 annotationAwareAspectJAutoProxyCreator,它执行 postProcessAfterInitialization(Object bean, String beanName) 方法,将目标类变成了代理类。(它解析切面的时机,不在赘述了)
至于@Import 注解是什么时候执行的,不用猜都知道它在 ConfigurationClassPostProcessor 类的processConfigBeanDefinitions() 方法中执行的。
AOP的实现过程 - 2、代理对象执行目标方法的过程 代理对象创建好了,最关键的时刻来了:代理对象执行目标方法并在恰当时机将通知织入 。