Spring初始化Ioc源码分析以及Aop原理分析(四)

xiaoxiao2021-02-28  52

Spring AOP原理

经过前面的分析,大致已经了解了Spring的原理,其中在使用的时候,有一个很重要的点就是AOP编程,什么是AOP,就不多做概述了,一句话:面向切面编程,在原有业务逻辑上,通过动态代理进行功能增强。 在Spring中主要是利用了BeanPostProcessor可以在Bean生命周期进行拦截的特性。因此主要有两步:

解析xml的时候,注册aop相关的BeanPostProcessor普通Bean初始化的时候BeanPostProcessor的作用

1.1 AnnotationAwareAspectJAutoProxyCreator 的解析

在ApplicationContext.xml 中,如果要使用aop需要有这样一个标签

<beans> <aop:aspectj-auto /> </beans>

在前面配置文件的解析分析中,说明了针对这种自定义的标签,一定会有一个对应的NameSpaceHandler处理器。针对aop标签的处理器就是AopNamespaceHandler

public void init() { this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); // 这里是解析的开始处 this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); } }

一直进入到下面这个方法

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { // 在这里就可以看到 AnnotationAwareAspectJAutoProxyCreator 这个类了 // 这个类就是aop相关的BeanPostProcessor实现类 return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }

具体是获取的就不详细分析了。

1.2 AnnotationAwareAspectJAutoProxyCreator 在运行期如何创建代理的

来看这个类的代码

public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator { private List<Pattern> includePatterns; private AspectJAdvisorFactory aspectJAdvisorFactory; private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder; public AnnotationAwareAspectJAutoProxyCreator() { } public void setIncludePatterns(List<String> patterns) { } public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) { } protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { } protected List<Advisor> findCandidateAdvisors() { } protected boolean isInfrastructureClass(Class<?> beanClass) { } protected boolean isEligibleAspectBean(String beanName) { } private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder { public BeanFactoryAspectJAdvisorsBuilderAdapter(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) { super(beanFactory, advisorFactory); } protected boolean isEligibleBean(String beanName) { return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName); } } }

在这个类的方法中,并没有典型的几个切面方法,所以需要去看它的父类,来看一下这个类的继承关系 可以看到AnnotationAwareAspectJAutoProxyCreator 中实现了BeanPostProcessor 和 InstantionAwareBeanPostProcessor ,而且基类是AbstarctAutoProxyCreator 类,在这个类中就可以看到我们想要看的东西

// bean实例化前执行的方法 public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = this.getCacheKey(beanClass, beanName); if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } if (beanName != null) { TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName); if (targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; } // 实例化后注入属性前 执行 public boolean postProcessAfterInstantiation(Object bean, String beanName) { return true; } // 上面的方法执行后,再执行这个方法 public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { return pvs; } // 注入属性后,bean执行初始化方法前,执行。 public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } // 注入属性后,bean执行初始化方法后,执行。 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = this.getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return this.wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }

观察上面几个切面方法,可以看到只有两个方法有实质性意义:

bean实例化前执行的方法 public Object postProcessBeforeInstantiation注入属性后,bean执行初始化方法后,再执行。 public Object postProcessAfterInitialization

1.2.1 postProcessBeforeInstantiation 方法解析

第一个方法作用是判断当前Bean可不可以被代理。

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { // 创造一个缓存key Object cacheKey = this.getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { // 是否已经包含这个cacheKey,即是否已经包含当前Bean了 if (this.advisedBeans.containsKey(cacheKey)) { return null; } /* 这个判断非常重要,第一个方法表示 是否是advice | PointCut | Advisor 等aop基类,是的话,先把这个类存储到advisedBeans中,标志位false,即不能代理。 第二个方法,是通过shouldSkip()方法,把当前Bean的所有通知和切面结合成Advisor通知器。最后判断是否应该跳过。 */ if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // 这里是问是否要自定义目标代理的,通常是返回null,所以,虽然下面代码也有创建代理 // 但通常不会执行,实际创建代理还是在postProcessAfterInitialization中 TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } else { return null; } }

1.2.2 postProcessAfterInitialization 方法解析

第二个方法就是根据第一个方法,实际生成代理类的地方

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = this.getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { // 继续进入方法中,这个是核心方法。 return this.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; } // 这里就是根据第一个取值去判断是否应该去获取代理类 // 很明显,如果前面存了false的就会直接返回。 else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 这里又出现了这两个方法,是为了保险起见的重复判断 // 在shouldSkip方法中,虽然也对切面进行了获取,但只是为了判断, // 下面的getAdvicesAndAdvisorsForBean方法才会返回切面 else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) { // 这个方法中,会将所有的通知器(切面) Advisors 返回到specificInterceptors 中。 Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 创建代理 Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }

上面的方法,就是经过一系列判断,最后到达最后两个步骤:

获取当前Bean相关的通知器(通知和切点的结合,也可以叫切面) protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { // 继续调用findEligibleAdvisors方法, List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName); // 根据获取到的通知器集合,判断是返回null,还是集合。 return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 这是获取所有通知器的方法 List<Advisor> candidateAdvisors = this.findCandidateAdvisors(); // 这是过滤出当前Bean应该应用的通知器的方法 List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); this.extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = this.sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }

由于通常使用的aop都是由注解来完成的,因此findCandidateAdvisors()方法应该也查看 AnnotationAwareAspectJAutoProxyCreator 类中的

protected List<Advisor> findCandidateAdvisors() { //调用父类的方法,作用是获取配置文件中的 通知 List<Advisor> advisors = super.findCandidateAdvisors(); if (this.aspectJAdvisorsBuilder != null) { // this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 这个方法是根据注解了@Aspect的类去获取通知器 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; } 根据获取的通知器,创建代理 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 (this.shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { this.evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors); // 把通知器放到生成代理的工厂中 proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); this.customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (this.advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 生成代理,里面会判断是采用JDK动态代理,还是cglib动态代理。 return proxyFactory.getProxy(this.getProxyClassLoader()); }

总结: aop的应用主要是利用了BeanPostProcessor的在Bean生命周期有前置和后置方法的特性,来在Bean初始化完成后,进行动态代理,使运行时使用的类,已经是被动态代理的代理类。 主要步骤:

通过AopNamespaceHandler 注册实现了BeanPostProcessor接口的AnnotationAwareAspectJAutoProxyCreator 类。在容器中的Bean实例化的时候,根据实例化前的前置方法 postProcessBeforeInstantiation 判断是否可以被代理。根据初始化后的后置方法 postProcessAfterInitialization 进行实际的代理创建,其中包括两步:获取当前Bean的所有切面(通知器)集合; 根据条件选择jdk动态代理或者cglib进行动态代理。

Spring中的事务,就是利用了AOP代理来实现的,Spring扩展的大部分功能都是通过AOP代理实现的。

ps:终于磕磕碰碰的写到了这里,这个系列就结束了。

转载请注明原文地址: https://www.6miu.com/read-2627412.html

最新回复(0)