spring framework

Spring AOP实现原理

2021-07-05  本文已影响0人  梦想实现家_Z

通过上一篇文章Spring Bean的创建过程及相关扩展点的介绍,我们知道getBean()创建Bean实例的过程,有以下几个扩展点:

SpringBoot如何实现Aop:

1.先从spring-boot-autoconfigure包下面的/META-INF/spring.factories开始,可以发现AopAutoConfiguration这个类,说明在引入spring-boot-autoconfigure这个jar包后,就会自动加载AopAutoConfiguration。

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(Advice.class)
    static class AspectJAutoProxyingConfiguration {

        @Configuration(proxyBeanMethods = false)
        @EnableAspectJAutoProxy(proxyTargetClass = false)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
                matchIfMissing = false)
        static class JdkDynamicAutoProxyConfiguration {

        }

        @Configuration(proxyBeanMethods = false)
        @EnableAspectJAutoProxy(proxyTargetClass = true)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
                matchIfMissing = true)
        static class CglibAutoProxyConfiguration {

        }
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnMissingClass("org.aspectj.weaver.Advice")
    @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
            matchIfMissing = true)
    static class ClassProxyingConfiguration {

        ClassProxyingConfiguration(BeanFactory beanFactory) {
            if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
                AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }
        }
    }
}

主要是看EnableAspectJAutoProxy这个注解,无论如何,这个注解都会生效

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
     * to standard Java interface-based proxies. The default is {@code false}.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
     * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
     * Off by default, i.e. no guarantees that {@code AopContext} access will work.
     * @since 4.3.1
     */
    boolean exposeProxy() default false;

}

进一步看一下

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * Register, escalate, and configure the AspectJ auto proxy creator based on the value
     * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
     * {@code @Configuration} class.
     */
    @Override
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    // 这是重点------这是重点------这是重点------
    // 这里就是注入AnnotationAwareAspectJAutoProxyCreator对象入口
        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);
            }
        }
    }
}
AnnotationAwareAspectJAutoProxyCreator类的UML图 image-20210701142934998.png

可以看到,AnnotationAwareAspectJAutoProxyCreator这个类是实现了InstantiationAwareBeanPostProcessor、SamrtInstantiationAwareBeanPostProcessor、BeanPostProcessor接口的,那么说明这个类是可以在Bean实例创建过程中,对Bean创建过程进行拦截和增强的。

同样的,AspectJAwareAdvisorAutoProxyCreator这个类其实就是基于XML配置来对Bean进行拦截和增强的。

1.在Bean实例化之前:

@Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        Object cacheKey = getCacheKey(beanClass, beanName);

        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }
    // 这是重点----这是重点-----这是重点
    // 从这里可以看出,这又是一种创建Bean实例的方式
    // 通过自定义的TargetSource来创建Bean实例。属于非常规用法。
        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      // 收集所有的Advisor后,通过MethodInterceptor创建代理。具体的实现可以是JDK或者CGLIB
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        return null;
    }

在此基础上,我们可以自定义一个BeanPostProcessor,针对AnnotationAwareAspectJAutoProxyCreator进行拦截,在AnnotationAwareAspectJAutoProxyCreator初始化生命周期中,给它创建一个TargetSource对象设置进去,这样就可以促使getCustomTargetSource()方法生效了。

2.另一个就是在Bean实例化后,把Bean对象放进第三级缓存中

// AbstractAutowireCapableBeanFactory类中587行
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
          // ********这是关键点********这是关键点********这是关键点********这是关键点********
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }

// AbstractAutoProxyCreator类中237行,AbstractAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor子类,是实现AOP的入口
@Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        this.earlyProxyReferences.put(cacheKey, bean);
    // ********这是关键点********这是关键点********这是关键点********这是关键点********
        return wrapIfNecessary(bean, beanName, cacheKey);
    }

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;
        }

        // 获取所有的Advisor实例,并筛选出匹配的Advisor实例
    // 获取Advisor的方式也是通过getBean()的方式,根据指定目标为Advisor.class查找
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 根据筛选出来的Advisor实例,创建代理对象
      // 如何创建的代理,其实就是使用了JDK动态代理或者CGLIB动态代理实现
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
      // 返回增强后的Bean对象
            return proxy;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

3.Bean初始化后

// AbstractAutoProxyCreator类中295行
@Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
        // ********这是关键点********同上********同上********这是关键点********
        // 和上面的wrapIfNecessary()一样
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

根据AbstractAutoProxyCreator来看,AOP切入的点有三个地方:

1.postProcessBeforeInstantiation():就是在Bean还没有创建出来之前,这个点是留给开发者自己扩展的。针对自定义TargetSource,检查是否有匹配的Advisor,如果有的话,那么就创建对应的代理对象。

2.postProcessAfterInitialization():这个就是Bean已经完成了初始化了,这个时候的Bean已经准备发布了,那么针对这个Bean对象,检查是否有匹配的Advisor,有的话,就创建对应的代理对象。

3.getEarlyBeanReference():这个就是Bean刚刚创建出来,还没有设置属性值,还不能发布,但是为了解决循环依赖的问题,需要先把这个Bean的引用发布出去。那么针对这个Bean就要检查是否有匹配的Advisor,有的话,创建代理对象。

在这三个扩展点,分别会做以下几件事情:

1.findCandidateAdvisors()方法获取所有的Advisor实例,并存放到一个数组里面;原理还是getBean()方式查找Advisor.class所有实例

2.findAdvisorsThatCanApply()方法从数组中筛选出拦截这个Bean的Advisor,有拦截class的,也有method;主要区分出IntroductionAdvisor、PointcutAdvisor;

3.针对筛选出来的Advisor排序

4.根据筛选出来的Advisor对象,通过ProxyFactory.getProxy()创建代理。

另外,再介绍两个手动编程创建代理对象的类:

以上两个类的区别在于,AspectJProxyFactory这个类里面有一个ReflectiveAspectJAdvisorFactory对象属性专门用来处理并生成Advisor、Advice。

共同点就是都能创建代理对象,主要是因为这两个类都继承自ProxyCreatorSupport。

上一篇下一篇

猜你喜欢

热点阅读