Spring源码学习笔记之AOP源码

得意时要看淡,失意时要看开。不论得意失意,切莫大意;不论成功失败,切莫止步。志得意满时,需要的是淡然,给自己留一条退路;失意落魄时,需要的是泰然,给自己觅一条出路Spring源码学习笔记之AOP源码,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、概述

Spring中的AOP其实是通过动态代理来实现的,在bean的后置处理时,通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来生成代理类

二、@EnableAspectJAutoProxy

我们知道开启AOP是通过EnableAspectJAutoProxy注解,不然所有的切面都不会生效,下面我们来看下这个注解做了哪些事

@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class MyConfig {
    ...
}

@Aspect
@Component
public class LogAspects {
    ...
}

点击注解EnableAspectJAutoProxy进去看

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

可以看到这边有Import注解,我们知道Import注解可以导入一个ImportBeanDefinitionRegistrar接口的实现类,实现类的registerBeanDefinitions方法会在容器刷新过程中的invokeBeanFactoryPostProcessors被调用,

具体一会看,我们先看看AspectJAutoProxyRegistrar这个类,混个眼熟

//AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      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

首先我们回顾下Spring核心方法refresh中的两个方法invokeBeanFactoryPostProcessors和registerBeanPostProcessors

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //省略...

        try {
            //省略...

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            //省略...
        }

        catch (BeansException ex) {
            //省略...
        }

        finally {
            //省略...
        }
    }
}

我们在AspectJAutoProxyRegistrar类的registerBeanDefinitions方法上打个断点,启动一下服务,可以看到通过容器刷新方法中的invokeBeanFactoryPostProcessors这一步,最终会走到AspectJAutoProxyRegistrar类的这个

registerBeanDefinitions方法中,其实这边的知识是关于Import注解相关的,以后有机会再详细说

Spring源码学习笔记之AOP源码

下面我们重点看下AspectJAutoProxyRegistrar类的registerBeanDefinitions方法

//AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
   @Override
   public void registerBeanDefinitions(
         AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

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

}

点击registerAspectJAnnotationAutoProxyCreatorIfNecessary进去,一路往里进,最终到AopConfigUtils类的registerOrEscalateApcAsRequired方法

//AopConfigUtils
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

//注意这个cls参数是AnnotationAwareAspectJAutoProxyCreator.class,记住这个类
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
        Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_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;
    }

    //包装成BeanDefinition
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    //把优先级调成最高
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    //注册AnnotationAwareAspectJAutoProxyCreator这个BeanDefinition,
    //名字叫org.springframework.aop.config.internalAutoProxyCreator
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

这个时候,AnnotationAwareAspectJAutoProxyCreator已经放到了beanDefinitionMap里,等待被实例化和初始化,那么AnnotationAwareAspectJAutoProxyCreator是在什么时候实例化和初始化的呢,我们先看下AnnotationAwareAspectJAutoProxyCreator的类图

Spring源码学习笔记之AOP源码

可以看到AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessor接口的实例,而BeanPostProcessor的实例化和初始化是registerBeanPostProcessors中完成的,我们找到这段代码,从上面我们知道AnnotationAwareAspectJAutoProxyCreator是加了Order属性的,所以走的是如下这段代码

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    //省略...

    // Next, register the BeanPostProcessors that implement Ordered.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    //省略...
}

可以看到9行getBean,点进去,进入到类AbstractBeanFactory的getBean方法

//AbstractBeanFactory
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    return doGetBean(name, requiredType, null, false);
}

看过Spring中bean初始化代码的小伙伴都熟悉了,doGetBean中就是对bean做初始化,到此时AnnotationAwareAspectJAutoProxyCreator完成了初始化,放到了容器中,我们知道AnnotationAwareAspectJAutoProxyCreator是实现了BeanPostProcessor接口的实例,会在bean对象创建之后调用其postProcessAfterInitialization方法,这个方法在抽象父类AbstractAutoProxyCreator中

//AbstractAutoProxyCreator
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            //包装如果必要的话
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

继续点击7行wrapIfNecessary进去

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

    // 看一看这个bean有没有通知方法或者增强器,如果有就创建代理对象
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        //把bean包装成代理对象proxy
        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;
}

点击18行createProxy进去

//AbstractAutoProxyCreator
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 proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);

    if (!proxyFactory.isProxyTargetClass()) {
        if (shouldProxyTargetClass(beanClass, beanName)) {
            proxyFactory.setProxyTargetClass(true);
        }
        else {
            evaluateProxyInterfaces(beanClass, proxyFactory);
        }
    }

    //将当前bean适合的advice,重新封装成Advisor类,然后添加到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());
}

点击34行getProxy进到ProxyFactory类的getProxy方法中

//ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
}

继续点击getProxy来到接口AopProxy中

//AopProxy
Object getProxy(@Nullable ClassLoader classLoader);

我们看看getProxy的实现

Spring源码学习笔记之AOP源码

可以看到分为两种创建代理类的方式,分别是jdk和cglib,选择jdk的方式看下

//JdkDynamicAopProxy
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    //jdk动态代理的标准用法
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

可以看到jdk动态代理的标准用法

四、过程总结

1、在容器刷新过程中的invokeBeanFactoryPostProcessors方法里把AnnotationAwareAspectJAutoProxyCreator注册到beanDefinitionMap里;

2、在容器刷新过程中的registerBeanPostProcessors方法里完成了初始化;

3、AnnotationAwareAspectJAutoProxyCreator类的postProcessAfterInitialization方法(实际在其父类AbstractAutoProxyCreator中)讲所有有advice的bean对象重新包装成proxy对象;

4、调用bean方法是会通过其代理类proxy来依次调用增强器的相关方法;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/154506.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!