zoukankan      html  css  js  c++  java
  • Spring AOP源码

    结合 Spring 后置处理器源码Spring Aware源码 ,再来看下 Spring AOP 的源码。

    启动 AOP

    使用 @EnableAspectJAutoProxy 这个注解来启用 AOP 的能力了。它使用 @Import 导入类 AspectJAutoProxyRegistrar,这个类实现了 ImportBeanDefinitionRegistrar,所以它会被 ConfigurationClassParser 扫描,并加入缓存中。然后 ConfigurationClassBeanDefinitionReader 从缓存中会拿到这个类,再执行其实现的方法 registerBeanDefinitions()。

    AspectJAutoProxyRegistrar.registerBeanDefinitions() 源码

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    }
    

    上述方法又使用 AOP 配置工具类 AopConfigUtils 将 AnnotationAwareAspectJAutoProxyCreator 也注册到 BeanFactory,其 name 为 org.springframework.aop.config.internalAutoProxyCreator。

    下图,展示了 AnnotationAwareAspectJAutoProxyCreator 的类继承关系
    AnnotationAwareAspectJAutoProxyCreator

    可以看出来 AnnotationAwareAspectJAutoProxyCreator 就是 BeanPostProcessor 和 Aware,其顶层抽象类 AbstractAutoProxyCreator 实现它们的接口。

    创建代理对象

    Spring Aware源码 中可知,BeanFactoryAware 实现类会在 invokeAwareMethods() 被回调 setBeanFactory() 方法,将 DefaultListableBeanFactory 注入给 AnnotationAwareAspectJAutoProxyCreator。

    InstantiationAwareBeanPostProcessor 新增了后置处理器方法 postProcessBeforeInstantiation() 和 postProcessAfterInstantiation(),这两个方法会在 Bean 初始化之前,也就是在 BeanPostProcessor 定义的方法之前先调用。

    • postProcessBeforeInstantiation() 会在反射调用 Bean 的构造器之前调用。
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 会返回一个代理对象,会执行 postProcessBeforeInstantiation()
    	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    	if (bean != null) {
    		return bean;
    	}
    	return doCreateBean(beanName, mbdToUse, args);
    }
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 从缓存获取
    	Object cacheKey = getCacheKey(beanClass, beanName);
    	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            // 判断是否已经在 advisedBeans 缓存
    		if (this.advisedBeans.containsKey(cacheKey)) {
    			return null;
    		}
    		// 判断 Bean 是否是 Advice/Pointcut/Advisor/AopInfrastructureBean 这些不需要代理的基础类型;或者是否 @Aspect 注解类
    		// 找到切面类中的所有通知方法,判断是否 AspectJPointcutAdvisor 类型,否则返回 false
    		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    			this.advisedBeans.put(cacheKey, Boolean.FALSE);
    			return null;
    		}
    	}
    	return null;
    }
    
    • postProcessAfterInstantiation() 会在给属性赋值的方法 populateBean() 中执行。
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) {
        // 属性赋值,会执行 postProcessAfterInstantiation()
    	populateBean(beanName, mbd, instanceWrapper);
    	// 执行 BeanPostProcessor 的方法
    	return initializeBean(beanName, exposedObject, mbd);
    }
    
    • BeanPostProcessor 的方法是在 initializeBean() 中才执行的。其中 postProcessAfterInitialization() 方法会获取切面类的所有通知方法,利用动态代理技术,创建增强的代理对象(比如:com.xxx.Service$$EnhancerBySpringCGLIB$$e86c6525@57eda880),同时会设置回调方法,完成后返回。
    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) {
        // 找到所有的候选通知方法
    	List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 从候选通知方法找到可用于当前 Bean 的通知
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    	// 获取所有的通知拦截器对象
    	Object[] specificInterceptors = eligibleAdvisors.toArray();
    	// 利用 AopProxy 来创建代理对象
    	// AopProxy 包含 JDK 和 CGLib 两种实现
    	Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    	return proxy;
    }
    

    至此,动态代理对象以及创建完成了,容器中就会有这个增强后的代理对象,方法执行时,也就会利用这个代理对象来执行通知方法了。

    执行代理对象

    执行被代理的方法时,会被 CglibAopProxy 拦截器拦截,获取这个方法的拦截器链。如果有拦截器链,则创建 CglibMethodInvocation 对象,执行 proceed(),即执行通知方法,最后返回 retVal,即方法的返回值;如果没有拦截器链,则直接执行方法;

    拦截器链实际上就是把方法拦截器放在 ArrayList 队列中,第一个默认是 ExposeInvocationInterceptor,剩下的默认顺序为 AspectJAfterThrowingAdvice、AspectJAfterReturningAdvice、AspectJAfterAdvice、AspectJAroundAdvice、AspectJMethodBeforeAdvice。

    proceed() 按照上面 ArrayList 中的顺序递归调用,当遇到 AspectJAroundAdvice、AspectJMethodBeforeAdvice 类型的通知时,会利用反射直接执行它们的通知方法,其他类型通知不会立即执行,会等待递归返回之后再行调用 invoke() 方法。这样,就能保证通知和方法的执行顺序:

    环绕通知执行 proceed() 前->前置通知->执行方法->环绕通知执行 proceed() 后->后置通知->返回通知->方法返回

    总结

    1. @EnableAspectJAutoProxy 使用 @Import(AspectJAutoProxyRegistrar.class) 导入 (AspectJAutoProxyRegistrar)ImportBeanDefinitionRegistrar。
    2. 容器刷新时,invokeBeanFactoryPostProcessors() 执行 (AspectJAutoProxyRegistrar)ImportBeanDefinitionRegistrar.registerBeanDefinitions() 注册 AnnotationAwareAspectJAutoProxyCreator 到 BeanFactory。
    3. AnnotationAwareAspectJAutoProxyCreator 实现了 InstantiationAwareBeanPostProcessor 和 BeanFactoryAware,在 registerBeanPostProcessors() 将其注册到 BeanFactory,并且执行 invokeAwareMethods() 回调 (AbstractAdvisorAutoProxyCreator)BeanFactoryAware.setBeanFactory() 方法。
    4. finishBeanFactoryInitialization() 执行 (AnnotationAwareAspectJAutoProxyCreator)BeanPostProcessor.postProcessAfterInitialization(),找到切面类及其切面通知方法,使用动态代理技术(ObjenesisCglibAopProxy/JdkDynamicAopProxy),对切面类进行增强,创建增强后的代理对象com.xxx.Service$$EnhancerBySpringCGLIB$$e86c6525@57eda880
    5. 执行被代理的方法时,会被 CglibAopProxy 的拦截器拦截,拿到方法的拦截器链,按顺序递归调用,利用反射技术执行通知方法,以此实现不同通知的调用顺序。
  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/bigshark/p/11324595.html
Copyright © 2011-2022 走看看