Spring5源码之AOP代理

这篇文章主要介绍了Spring5源码之AOP代理,是基于上一篇Spring5源码之AOP增强器获取所有对应的bean之后,就开始创建AOP代理了。需要的朋友可以参考一下。

1、创建代理

在获取所有对应的bean的增强器,便可以进行代理的创建了。

/**
 1. 对给定的bean创建AOP代理
*/
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);
	}

	// 1 创建代理工厂类
	ProxyFactory proxyFactory = new ProxyFactory();
	// 2 获取当前类中相关属性
	proxyFactory.copyFrom(this);
	// 3 决定对于给定的bean是否应该使用targetClass而不是它的接口代理,检查proxyTargetClass设置以及
	if (!proxyFactory.isProxyTargetClass()) {
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			// 添加代理接口
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	//  加入增强器
	proxyFactory.addAdvisors(advisors);
	// 4 设置要代理的类
	proxyFactory.setTargetSource(targetSource);
	// 5 定制代理
	customizeProxyFactory(proxyFactory);
	// 6 用来控制代理工厂被配置之后,是否还允许修改通知,缺省值为false(即在代理被配置之后,不允许修改代理的配置)
	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}

	return proxyFactory.getProxy(getProxyClassLoader());
}

对于代理类的创建及处理,Spring委托给了ProxyFactory去处理,而在此方法中主要是对ProxyFactory的初始化操作,进而对真正的创建代理做准备,这些初始化操作包含以下内容。

  • 1.获取当前类的属性。
  • 2.添加代理接口。
  • 3.封装Advisor并加入到ProxyFactory。
  • 4.设置要代理的类。
  • 5.当然在Spring中还为子类提供了定制的方法customizeProxyFactory,子类可以覆盖在方法中进行对ProxyFactory的进一步封装。
  • 6.进行获取代理操作。
    其中封装Advisor并加入到ProxyFactory中以及创建代理是两个相对繁琐的过程,可以通过ProxyFactory提供的addAdvisors方法直接将增强器置入代理创建工厂中,但是将拦截器封装为增强器还是需要一定的逻辑的。

2、buildAdvisors

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	// 解析注册的所有interceptorNames
	Advisor[] commonInterceptors = resolveInterceptorNames();

	List<Object> allInterceptors = new ArrayList<>();
	if (specificInterceptors != null) {
		// 加入拦截器
		allInterceptors.addAll(Arrays.asList(specificInterceptors));
		if (commonInterceptors.length > 0) {
			if (this.applyCommonInterceptorsFirst) {
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
			}
			else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));
			}
		}
	}
	if (logger.isDebugEnabled()) {
		int nrOfCommonInterceptors = commonInterceptors.length;
		int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
		logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
				" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
	}

	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		// 拦截器进行封装转换为Advisor
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
	// 如果要封装的对象本身就是Advisor类型,那么无须再做过多处理
	if (adviceObject instanceof Advisor) {
		return (Advisor) adviceObject;
	}
	// 因为此封装方法只对Advisor与Advice两种类型的数据有效,如果不是讲不能封装
	if (!(adviceObject instanceof Advice)) {
		throw new UnknownAdviceTypeException(adviceObject);
	}
	Advice advice = (Advice) adviceObject;
	if (advice instanceof MethodInterceptor) {
		// 如果是MethodInterceptor类型则使用DefaultPointcutAdvisor封装
		return new DefaultPointcutAdvisor(advice);
	}
	// 如果存在AdvisorAdapter那么也同学需要进行封装
	for (AdvisorAdapter adapter : this.adapters) {
		if (adapter.supportsAdvice(advice)) {
			return new DefaultPointcutAdvisor(advice);
		}
	}
	throw new UnknownAdviceTypeException(advice);
}

由于Spring中涉及过多的拦截器、增强器、增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成Advisor来进行代理的创建,完成了增强的封装过程,那么解析就是代理的创建与获取了。

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

protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	// 创建代理
	return getAopProxyFactory().createAopProxy(this);
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
		Class<?> targetClass = config.getTargetClass();
		if (targetClass == null) {
			throw new AopConfigException("TargetSource cannot determine target class: " +
					"Either an interface or a target is required for proxy creation.");
		}
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

至此已经完成了代理的创建,不管我们之前是否阅读过Spring的源代码,但是都或多或少地听过对于Spring的代理中JDKProxy的实现和CglibProxy的实现。

从if中的判断条件可以看到3个方面影响着Spring的判断。
optimize:用来控制通过Cglib创建的代理是否使用激进的优化策略。除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于Cglib代理,对于JDK动态代理(默认代理)无效。
proxyTargetClass:这个属性为false时,JDK动态代理将被创建,如果这个属性值为true,Cglib代理将被创建。设置方式为<aop:aspectj-autoproxy proxy-target-class=“true” />
hasNoUserSuppliedProxyInterfaces:是否存在代理接口。

3、JDK与Cglib方式的总结

  • 1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。
  • 2、如果目标对象实现了接口,可以强制使用Cglib实现AOP。
  • 3、如果目标对象没有实现接口,必须采用Cglib库,Spring会自动在JDK动态代理和Cglib之间转换。

4、JDK动态代理和Cglib字节码生成的区别

  • 1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
  • 2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类活方法最后不要声明成final。

如果您觉得有帮助,欢迎点赞收藏哦 ~ ~ 多谢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值