温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Spring源码如何实现动态代理

发布时间:2021-03-29 10:51:52 来源:亿速云 阅读:201 作者:小新 栏目:开发技术

小编给大家分享一下Spring源码如何实现动态代理,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

注:这里不阐述Spring和AOP的一些基本概念和用法,直接进入正题。

流程

  Spring所管理的对象大体会经过确定实例化对象类型、推断构造方法创建对象(实例化)、设置属性、初始化等等步骤。在对象初始化阶段,Spring为开发者提供了一个BeanPostProcessor接口,它会在对象初始化之前和初始化之后被调用(初始化,不是实例化,对应实例化的是InstantiationAwareBeanPostProcessor接口)。

public interface BeanPostProcessor {	//初始化之前	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;	//初始化之后	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }

  在对象初始化之后会调用postProcessAfterInitialization方法,该方法返回一个Object。如果成功返回了一个对象,那么容器中相应beanName对应的实例就将会是这个对象。

  本文主要分析动态代理,我们着重看AnnotationAwareAspectJAutoProxyCreator。先来看一下它的继承关系:

Spring源码如何实现动态代理

  AnnotationAwareAspectJAutoProxyCreator最终实现了BeanPostProcessor接口(也实现了InstantiationAwareBeanPostProcessor接口),可以看到继承关系比较复杂。当前我们关注的postProcessAfterInitialization方法实现在它的父类AbstractAutoProxyCreator中(只保留了部分代码):

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {	if (bean != null) {	Object cacheKey = getCacheKey(bean.getClass(), beanName);	if (!this.earlyProxyReferences.contains(cacheKey)) {	return wrapIfNecessary(bean, beanName, cacheKey);	}	}	return bean;	}

  这里主要看看wrapIfNecessary方法(只保留了部分代码):

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);	......	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);	if (specificInterceptors != DO_NOT_PROXY) {	this.advisedBeans.put(cacheKey, Boolean.TRUE);	Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));	this.proxyTypes.put(cacheKey, proxy.getClass());	return proxy;	}	...... }

  其中核心的是两个方法调用,分别是getAdvicesAndAdvisorsForBean和createProxy。getAdvicesAndAdvisorsForBean会返回一个对象数组,包含aop相关的一些对象,如果是一个普通的不需要代理的对象会返回一个空Object数组,也就是DO_NOT_PROXY;createProxy方法则是创建代理类。

  先看看getAdvicesAndAdvisorsForBean方法:

protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) throws BeansException;

  getAdvicesAndAdvisorsForBean方法在当前类(AbstractAutoProxyCreator)中是一个抽象方法,由子类AbstractAdvisorAutoProxyCreator实现:

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {	@Override	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);	if (advisors.isEmpty()) {	return DO_NOT_PROXY;	}	return advisors.toArray();	} }

  代码很清晰,我们进入findEligibleAdvisors方法,看方法名也知道它会完成寻找Advisor的工作:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {	//寻找Advisor	List<Advisor> candidateAdvisors = findCandidateAdvisors();	//针对指定的bean,过滤可用的Advisor,比如根据注解匹配	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);	extendAdvisors(eligibleAdvisors);	if (!eligibleAdvisors.isEmpty()) {	eligibleAdvisors = sortAdvisors(eligibleAdvisors);	}	return eligibleAdvisors;	}

  首先进入findCandidateAdvisors方法:

protected List<Advisor> findCandidateAdvisors() {	// Add all the Spring advisors found according to superclass rules.	List<Advisor> advisors = super.findCandidateAdvisors();	// Build Advisors for all AspectJ aspects in the bean factory.	advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());	return advisors;	}

  我们这里主要看看aspectj的逻辑,所以看看aspectJAdvisorsBuilder.buildAspectJAdvisors方法(只保留了主要代码):

public List<Advisor> buildAspectJAdvisors() {	List<String> aspectNames = null;	......	synchronized (this) {	aspectNames = this.aspectBeanNames;	if (aspectNames == null) {	//获取所有管理的beanName	String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);	//遍历每个beanName	for (String beanName : beanNames) {	//从beanFactory获取Class	Class<?> beanType = this.beanFactory.getType(beanName);	//检查对应的Class是否实现Aspect注解	if (this.advisorFactory.isAspect(beanType)) {	//说明这个beanName对应的类是一个切面	aspectNames.add(beanName);	AspectMetadata amd = new AspectMetadata(beanType, beanName);	if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {	MetadataAwareAspectInstanceFactory factory =	new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);	//获取Advisor,主要是解析对象中关于AOP的注解,比如Pointcut	List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);	if (this.beanFactory.isSingleton(beanName)) {	//就放入缓存,后面就不用重新解析了	this.advisorsCache.put(beanName, classAdvisors);	}	advisors.addAll(classAdvisors);	}	}	}	this.aspectBeanNames = aspectNames;	return advisors;	}	}	...... }

  会从beanFactory中寻找所有管理的beanName,返回一个String数组,然后遍历数组,从beanFactory中根据beanName获取对应的Class,然后再看对应的Class是否有Aspect注解,如果有对应的注解,那么就表示这个对象是一个切面。接下来就需要进行解析,生成真正的Advisor对象,最后放入缓存。

  可以看看isAspect方法是如何判断的:

@Override	public boolean isAspect(Class<?> clazz) {	return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));	}	private boolean hasAspectAnnotation(Class<?> clazz) {	return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);	}

  逻辑很清晰,主要就是看有没有Aspect注解。 但是这里要注意,这个buildAspectJAdvisors方法通常不是在这里调用的(”这里“的意思是postProcessAfterInitialization的流程)。回到AnnotationAwareAspectJAutoProxyCreator继承关系图中,它也实现了InstantiationAwareBeanPostProcessor接口,同样在其父类AbstractAutoProxyCreator中实现了postProcessBeforeInstantiation方法,这个方法会在对象实例化(不是初始化)之前调用,在该方法的逻辑里通常会首先触发buildAspectJAdvisors方法的执行,执行之后会把结果缓存起来。

  好了,再回到findEligibleAdvisors方法,上面代码已经贴了,这里就不贴了。获取到Advisor列表之后,要从中找到能用于指定类的Advisor列表,然后返回。接下来就要为指定的对象创建代理对象了,也就是AbstractAutoProxyCreator类的createProxy方法:

protected Object createProxy(	Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {	ProxyFactory proxyFactory = new ProxyFactory();	proxyFactory.copyFrom(this);	if (!proxyFactory.isProxyTargetClass()) {	if (shouldProxyTargetClass(beanClass, beanName)) {	proxyFactory.setProxyTargetClass(true);	}	else {	evaluateProxyInterfaces(beanClass, proxyFactory);	}	}	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);	for (Advisor advisor : advisors) {	proxyFactory.addAdvisor(advisor);	}	proxyFactory.setTargetSource(targetSource);	customizeProxyFactory(proxyFactory);	proxyFactory.setFrozen(this.freezeProxy);	if (advisorsPreFiltered()) {	proxyFactory.setPreFiltered(true);	}	return proxyFactory.getProxy(getProxyClassLoader());	}

  代理对象是由ProxyFactory代理工厂创建的,我们先看看这个工厂是如何创建代理对象的,也就是proxyFactory.getProxy方法:

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

  createAopProxy方法会返回一个AopProxy,该方法定义在ProxyFactory的父类ProxyCreatorSupport中:

public class ProxyCreatorSupport extends AdvisedSupport {	private AopProxyFactory aopProxyFactory;	public ProxyCreatorSupport() {	//设置默认的代理工厂DefaultAopProxyFactory	this.aopProxyFactory = new DefaultAopProxyFactory();	}	public AopProxyFactory getAopProxyFactory() {	//获取代理工厂,默认就是DefaultAopProxyFactory	return this.aopProxyFactory;	}	protected final synchronized AopProxy createAopProxy() {	//先获取代理工厂,然后调用工厂的createAopProxy方法创建AopProxy	return getAopProxyFactory().createAopProxy(this);	} }

  上面贴出了关键代码,getAopProxyFactory默认返回的是一个DefaultAopProxyFactory工厂类,来看看DefaultAopProxyFactory的createAopProxy方法:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {	Class<?> targetClass = config.getTargetClass();	if (targetClass.isInterface()) {	return new JdkDynamicAopProxy(config);	}	return new ObjenesisCglibAopProxy(config);	}	else {	return new JdkDynamicAopProxy(config);	}	}

  代码中有一些代理配置的判断,这里不用关心。可以看到它提供了两个AopProxy,分别是基于JDK的JdkDynamicAopProxy和基于cglib的ObjenesisCglibAopProxy。由于JDK提供的动态代理实现最终生成的代理类默认会继承Proxy类,实现被代理类实现的接口,因为Java是单继承,所以只能通过接口实现,也就限制了要使用JDK提供的动态代理,必须要基于接口。而使用cglib基于字节码的改造则没有这个限制,所以Spring提供了这两种方式,根据被代理类的实际情况来选择。

  关于每个AopProxy是如何创建代理类的,这里就先不跟了~

总结

  总的来说,动态代理是实现AOP的重要手段,Spring提供的动态代理主要依靠其提供的BeanPostProcessor,也称之为后置处理器。除了BeanPostProcessor之外,还有InstantiationAwareBeanPostProcessor(也继承了BeanPostProcessor),它们会在bean的生命周期的特定阶段被调用,以开放给开发者处理和调整对象的入口或者手段。动态代理依托后置处理器,在后置处理器的逻辑中使用AopProxy创建了被代理对象的代理类,然后代替原有类存入Spring的bean工厂中,之后根据beanName获取的实例对象就不再是原对象实例,而是代理类。而AopProxy是由AopProxyFactory接口生成,目前该接口只有DefaultAopProxyFactory实现类,其提供了两种AopProxy,分别基于原生JDK提供的动态代理和cgib,根据实际情况选择。

Spring源码如何实现动态代理

看完了这篇文章,相信你对“Spring源码如何实现动态代理”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI