返回

Spring5 AOP——创建AOP动态代理

发布时间:2023-01-10 20:00:47 233
# java# java# 容器# 信息

Spring AOP的总体流程

  • 1、注册解析AOP的服务
  • 2、解析和加载横切逻辑
  • 3、将横切逻辑织入目标Bean中

AnnotationAwareAspectJAutoProxyCreator继承体系图

AnnotationAwareAspectJAutoProxyCreator既实现了SmartInstantiationAwareBeanPostProcessor 又实现了BeanFactoryAware。就可以对容器做一些事情。

 

AnnotationAwareAspectJAutoProxyCreator 实现了Order接口,所以先于普通的BeanPostProcessor注册,并对普通BeanPostProcessor也能起作用。

 

AnnotationAwareAspectJAutoProxyCreator 是InstantiationAwareBeanPostProcessor,会在Bean被创建之前,在resolveBeforeInstantiation中被调用。

 

Spring Aop主要是通过AbstractAutoProxyCreator实现的BeanPostProcessor、InstantiationAwareBeanPostProcessor以及SmartInstantiationAwareBeanPostProcessor接口里面的后置处理器方法,来介入到Spring IOC容器的Bean的实例化以及初始化的过程中对Bean进行AOP的处理的。

 

所以AbstractAutoProxyCreator类里面的实现的容器级别的后置处理器方法便是介入分析的点:

  • 横切逻辑的加载主要是在AbstractAutoProxyCreator类中的postProcessBeforeInstantiation方法中,该方法是在Bean的实例化之前被调用的。

  • 横切逻辑织入目标Bean中主要是在AbstractAutoProxyCreator类中的postProcessAfterInitialization方法中,该方法是在Bean的实例化之后被调用的。

Spring AOP横切逻辑的织入过程:

在Spring5AOP——AbstractAutoProxyCreator横切逻辑织入目标Bean中文章中,分析了横切逻辑织入目标Bean中,本文就分析AbstractAutoProxyCreator类中wrapIfNecessary方法中的createProxy方法,创建AOP动态代理。

wrapIfNecessary

  • 判断当前bean是否需要被代理,如果需要则创建动态代理类。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
        implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    /**
     * Spring实现Bean代理的核心方法。wrapIfNecessary在两处会被调用,一处是getEarlyBeanReference,
     * 另一处是postProcessAfterInitialization
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        //已经被处理过
        // 1.判断当前bean是否在targetSourcedBeans缓存中存在(已经处理过),如果存在,则直接返回当前bean
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        //不需要被织入逻辑的
        // 2.在advisedBeans缓存中存在,并且value为false,则代表无需处理
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
        //是不是基础的bean 是不是需要跳过的
        // 3.bean的类是aop基础设施类 || bean应该跳过,则标记为无需处理,并返回
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // Create proxy if we have advice.
        // 返回匹配当前Bean的所有Advice\Advisor\Interceptor
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        // 5.如果存在增强器则创建代理
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //创建Bean对应的代理,SingletonTargetSource用于封装实现类的信息
            // 5.1 创建代理对象:这边SingletonTargetSource的target属性存放的就是我们原来的bean实例(也就是被代理对象),
            // 用于最后增加逻辑执行完毕后,通过反射执行我们真正的方法时使用(method.invoke(bean, args))
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            // 5.2 创建完代理后,将cacheKey -> 代理类的class放到缓存
            this.proxyTypes.put(cacheKey, proxy.getClass());
            // 返回代理对象
            return proxy;
        }
        //该Bean是不需要进行代理的,下次就不需要重复生成了
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
}
  • 当执行完getAdvicesAndAdvisorsForBean方法之后,就可以从候选的Advisor列表里筛选出匹配于当前Bean的Advisor列表,获取到Advisor列表之后就会接着执行后续的创建动态代理的步骤了。

  • 由于getAdvicesAndAdvisorsForBean筛选出匹配的Advisor了,将该Bean对应的cacheKey写入到advisedBeans中,并将对应的值设置为true,表示对该Bean进行过Spring AOP的处理了。

  • 之后就会调用createProxy方法去创建目标代理对象实例,创建好动态代理实例之后,就会动态代理实例类型给保存到proxyTypes的缓存里面,并将动态代理实例返回,这样就完成了wrapIfNecessary方法的执行。

  • 如果没有getAdvicesAndAdvisorsForBean没有筛选出匹配的Advisor的话,就证明该Bean不需要织入横切逻辑,此时就会在advisedBeans里给该Bean设置对应的cacheKey和false,以表明该bean是不需要被织入的。

本文重点分析createProxy方法——创建AOP动态代理

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
		//如果beanFactory是ConfigurableListableBeanFactory的类型,暴露目标类
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		//创建一个ProxyFactory,当前ProxyCreator在创建代理时将需要用到的字段赋值到ProxyFactory中去
		ProxyFactory proxyFactory = new ProxyFactory();
		//将 当前的AnnotationAwareAspectJAutoProxyCreator 对象的属性赋值给ProxyFactory对象
		proxyFactory.copyFrom(this);
		// 处理 proxyTargetClass 属性
		// 如果希望使用 CGLIB 来代理接口,可以配置
		// proxy-target-class="true",这样不管有没有接口,都使用 CGLIB 来生成代理:
		// 
		if (!proxyFactory.isProxyTargetClass()) {
			// 检查preserveTargetClass属性,判断beanClass是应该基于类代理还是基于接口代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				// 如果是基于类代理,则将proxyTargetClass赋值为true
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				// 评估bean的代理接口
				// 1. 有接口的,调用一次或多次:proxyFactory.addInterface(ifc);
				// 2. 没有接口的,调用:proxyFactory.setProxyTargetClass(true);
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		// 这个方法主要来对前面传递进来的横切逻辑实例进行包装
		// 注意:如果 specificInterceptors 中有 Advice 和 Interceptor,它们也会被包装成 Advisor
		// 方法会整理合并得到最终的advisors (毕竟interceptorNames还指定了一些拦截器的)
		// 至于调用的先后顺序,通过方法里的applyCommonInterceptorsFirst参数可以进行设置,
		// 若applyCommonInterceptorsFirst为true,interceptorNames属性指定的Advisor优先调用。默认为true
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		// 将advisors添加到proxyFactory
		proxyFactory.addAdvisors(advisors);
		// 设置要代理的类,将targetSource赋值给proxyFactory的targetSource属性,之后可以通过该属性拿到被代理的bean的实例
		proxyFactory.setTargetSource(targetSource);
		// 这个方法是交给子类的,子类可以继续去定制此proxyFactory
		customizeProxyFactory(proxyFactory);

		// 用来控制proxyFactory被配置之后,是否还允许修改通知。默认值为false(即在代理被配置之后,不允许修改代理类的配置)
		proxyFactory.setFrozen(this.freezeProxy);
		// 设置preFiltered的属性值,默认是false。子类:AbstractAdvisorAutoProxyCreator修改为true
		// preFiltered字段意思为:是否已为特定目标类筛选Advisor
		// 这个字段和DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice获取所有的Advisor有关
		//CglibAopProxy和JdkDynamicAopProxy都会调用此方法,然后递归执行所有的Advisor
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// 使用proxyFactory获取代理
		return proxyFactory.getProxy(getProxyClassLoader());
	}
}

evaluateProxyInterfaces(beanClass, proxyFactory)

  • 根据被代理beanClass是否实现了接口,来评估是调用CGLIB还是JDK动态代理。
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {

	/**
	 * 这里决定了如果目标类没有实现接口直接就是Cglib代理
	 * 检查给定beanClass上的接口们,并交给proxyFactory处理
	 */
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
		// 找到该类实现的所有接口们
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		// 标记:是否有存在合理的接口
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) {
			if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
					ifc.getMethods().length > 0) {
				hasReasonableProxyInterface = true;
				break;
			}
		}
		if (hasReasonableProxyInterface) {
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			//不管接口是否合理,都将其添加进去
			for (Class<?> ifc : targetInterfaces) {
				proxyFactory.addInterface(ifc);
			}
		}
		else {
			proxyFactory.setProxyTargetClass(true);
		}
	}
}

buildAdvisors(beanName, specificInterceptors)

  • 对横切逻辑实例进行包装
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		// 解析interceptorNames而来得Advisor数组
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			// 添加参数传进来的,即前面解析出来的advisors
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			if (commonInterceptors.length > 0) {
				// 添加拦截器
				//调用的先后顺序,通过applyCommonInterceptorsFirst参数可以进行设置,
				// 若applyCommonInterceptorsFirst为true,interceptorNames属性指定的Advisor优先调用。
				// 默认为true
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		if (logger.isTraceEnabled()) {
			int nrOfCommonInterceptors = commonInterceptors.length;
			int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
			logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
					" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
		}
		//把拦截器包装为Advisor
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			// wrap包装
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}
}
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线