Spring AOP源码:代理的创建过程

文章导航

Spring AOP:基本概述
Spring AOP源码:配置文件解析过程
Spring AOP源码:配置文件解析过程
Spring AOP源码:拦截器责任链处理过程

前言

上篇文章讲解了AOP解析工作,将配置文件解析并封装成beanDefinition,由于配置文件中有5个通知方法,before、after、around、after-returning、after-throwing,这里会将其解析成5个advisor通知类。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

		<bean id="accountAdvice" class="service.impl.AccountAdvice" ></bean>
		<bean id="myAccount" class="service.impl.MyAccount" ></bean>

		<aop:config>
			<aop:pointcut id="pointCut" expression="execution(* service.impl.*.*())"/>
			<aop:aspect ref="accountAdvice">
				<aop:after method="after" pointcut-ref="pointCut"></aop:after>
				<aop:before method="before" pointcut-ref="pointCut"></aop:before>
				<aop:around method="around" pointcut-ref="pointCut"></aop:around>
				<aop:after-returning method="afterReturn" pointcut-ref="pointCut"></aop:after-returning>
				<aop:after-throwing method="afterThrow" pointcut-ref="pointCut"></aop:after-throwing>
			</aop:aspect>
		</aop:config>


</beans>

解析后的BeanDefinitions集合信息:

在这里插入图片描述

正文

之前Spring IOC文章讲解过Bean的实例化过程,在实例化Bean之后会进行属性填充(populateBean)、执行初始化方法(initializeBean)。而代理类的生成就在执行初始化方法(initializeBean)中,在该方法中会执行beanPostProcessor方法,如果该bean需要代理,则会进行代理工作。

本章案例中需要被代理的类是myAccount,所以我们来到myAccount实例化过程中的initializeBean方法中;

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    
    
		// 如果安全管理器不为空
		if (System.getSecurityManager() != null) {
    
    
			// 以特权的方式执行回调bean中的Aware接口方法
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    
    
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
    
    
			// Aware接口处理器,调用BeanNameAware、BeanClassLoaderAware、beanFactoryAware
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//如果mdb不为null || mbd不是"synthetic"。一般是指只有AOP相关的prointCut配置或者Advice配置才会将 synthetic设置为true
		if (mbd == null || !mbd.isSynthetic()) {
    
    
			// 将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessBeforeInitialization初始化方法。
			// 返回的Bean实例可能是原始Bean包装器
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
    
    
			//调用初始化方法,先调用bean的InitializingBean接口方法,后调用bean的自定义初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
    
    
			//捕捉调用初始化方法时抛出的异常,重新抛出Bean创建异常:调用初始化方法失败
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//如果mbd为null || mbd不是"synthetic"
		if (mbd == null || !mbd.isSynthetic()) {
    
    
			// 将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessAfterInitialization方法。
			// 返回的Bean实例可能是原始Bean包装器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		//返回包装后的Bean
		return wrappedBean;
	}

AOP的代理类生成过程在BeanPostProcessor的after方法中调用

applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName),见方法1详解

方法1:postProcessAfterInitialization

进入到AspectJAwareAdivsorAutoProxyCreator类中的postProcessAfterInitialization方法;

	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    
    
		if (bean != null) {
    
    
			// 获取当前bean的key:如果beanName不为空,则以beanName为key,如果为FactoryBean类型则beanName名称前面会加上“&”符号
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// 判断当前bean是否正在被代理,如果正在被代理则不进行代理操作
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    
    
				// 如果它需要被代理,则需要封装指定的bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

wrapIfNecessary(bean, beanName, cacheKey),见方法2详解

方法2:wrapIfNecessary

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    
    
		// 判断是否已经处理过,处理过则直接返回
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    
    
			return bean;
		}
		// 这里advisedBeans缓存了已经进行了代理流程处理的bean,如果缓存中存在,则可以直接返回
		//这里存在两种bean,一种是不需要代理的bean,一种是真正需要代理的,避免下次判断时可以直接返回,不走下面处理逻辑
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    
    
			return bean;
		}
		// 这里isInfrastructureClass()用于判断当前bean是否为Spring系统自带的bean,如:Advice、Pointcut、Advisor、AopInfrastructureBean的实现类
		// 不用进行代理的;shouldSkip()则用于判断当前bean是否应该被略过
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    
    
			// 对当前bean进行缓存
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 尝试获取能够匹配当前被代理类的通知类信息
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// 如果找到合适的通知类,则进行代理操作
		if (specificInterceptors != DO_NOT_PROXY) {
    
    
			// 对当前bean的代理状态进行缓存
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 根据获取到的Advices和Advisors为当前bean生成代理对象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			// 缓存生成的代理bean的类型,并且返回生成的代理bean
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

shouldSkip(bean.getClass(), beanName),见方法3详解
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null),见方法4详解
createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)),见方法7详解

方法3:shouldSkip

	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    
    
		// TODO: Consider optimization by caching the list of the aspect names
		//尝试从beanFacotry工厂中获取配置文件中定义好的五个通知方法,它们被封装成了advisor对象,所以这里能获取到5个
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
    
    
			//判断通知类中的切面类名称,如果当前bean是切面类,则不应该被代理,会跳过
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
    
    
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

方法4:getAdvicesAndAdvisorsForBean

	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    
    

		// 找合适的增强器对象
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		// 若为空表示没找到
		if (advisors.isEmpty()) {
    
    
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    
    
		// 将当前系统中所有的切面类的切面逻辑进行封装,从而得到目标Advisor
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 对获取到的所有Advisor进行判断,判断其中的表达式是否能够匹配上要被代理的类
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		// 提供的hook方法,用于对目标Advisor进行扩展
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
    
    
			// 对需要代理的Advisor按照一定的规则进行排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName),见方法5详解
extendAdvisors(eligibleAdvisors),见方法6详解

方法5:findAdvisorsThatCanApply

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
    

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
    
    
			// 从候选的通知器中找到合适正在创建的实例对象的通知器
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
    
    
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
    
    
		// 若候选的增强器集合为空 直接返回
		if (candidateAdvisors.isEmpty()) {
    
    
			return candidateAdvisors;
		}
		// 定义一个合适的增强器集合对象
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		// 循环我们候选的通知类对象
		for (Advisor candidate : candidateAdvisors) {
    
    
			// 判断我们的通知类对象是不是实现了IntroductionAdvisor 
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
    
    
				eligibleAdvisors.add(candidate);
			}
		}
		// 判断是否有合适的通知类
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
    
    
			// 判断我们的通知类对象是不是实现了IntroductionAdvisor
			if (candidate instanceof IntroductionAdvisor) {
    
    
				// already processed
				// 在上面已经处理过,不需要处理
				continue;
			}

			// 真正的判断增强器是否合适当前类型,这里会通过切入点表达式进行判断是否适用于当前类
			if (canApply(candidate, clazz, hasIntroductions)) {
    
    
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

方法6:extendAdvisors

	protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    
    
		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
	}
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
    
    
		// Don't add advisors to an empty list; may indicate that proxying is just not required
		if (!advisors.isEmpty()) {
    
    
			boolean foundAspectJAdvice = false;
			for (Advisor advisor : advisors) {
    
    
				// Be careful not to get the Advice without a guard, as this might eagerly
				// instantiate a non-singleton AspectJ aspect...
				//判断是否是通知类,并将其属性打上标签
				if (isAspectJAdvice(advisor)) {
    
    
					foundAspectJAdvice = true;
					break;
				}
			}
			//这里会往advisors缓存中添加ExposeInvocationInterceptor对象,该对象为后续代理类调用过程中的拦截链做准备
			if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
    
    
				advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
				return true;
			}
		}
		return false;
	}

方法7:createProxy

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
    
    

		// 给bean定义设置暴露属性
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
    
    
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		// 创建代理工厂
		ProxyFactory proxyFactory = new ProxyFactory();
		// 获取当前类中相关属性
 		proxyFactory.copyFrom(this);
		// 决定对于给定的bean是否应该使用targetClass而不是他的接口代理,检查proxyTargetClass设置以及preserverTargetClass属性
		if (!proxyFactory.isProxyTargetClass()) {
    
    
			// 判断是 使用jdk动态代理 还是cglib代理
			//如果被代理类有preserveTargetClass,则设置ProxyTargetClass为true,尝试使用Cglib进行代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
    
    
				proxyFactory.setProxyTargetClass(true);
			}
			else {
    
    
				// 判断是否有实现接口,如果没有实现接口则设置setProxyTargetClass为true,尝试使用Cglib进行代理
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		// 将被代理类名称及其适配的通知对象构建通知类
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		// 设置到要代理的类
		proxyFactory.setTargetSource(targetSource);
		//空方法,用于子类拓展实现
		customizeProxyFactory(proxyFactory);

		// 控制代理工程被配置之后,是否还允许修改通知,默认值是false
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
    
    
			proxyFactory.setPreFiltered(true);
		}
		// 真正创建代理对象
		return proxyFactory.getProxy(getProxyClassLoader());
	}

proxyFactory.getProxy(getProxyClassLoader()),见方法8详解

方法8:getProxy

	public Object getProxy(@Nullable ClassLoader classLoader) {
    
    
		// createAopProxy() 用来创建我们的代理工厂
		return createAopProxy().getProxy(classLoader);
	}
	protected final synchronized AopProxy createAopProxy() {
    
    
		if (!this.active) {
    
    
			// 监听调用AdvisedSupportListener实现类的activated方法
			activate();
		}
		// 通过AopProxyFactory获得AopProxy,这个AopProxyFactory是在初始化函数中定义的,使用的是DefaultAopProxyFactory
		return getAopProxyFactory().createAopProxy(this);
	}

getAopProxyFactory().createAopProxy(this),见方法9详解

方法9:createAopProxy

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    
    
		// 这段代码用来判断选择哪种创建代理对象的方式
		// config.isOptimize()   是否对代理类的生成使用策略优化 其作用是和isProxyTargetClass是一样的 默认为false
		// config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象 默认为false
		// hasNoUserSuppliedProxyInterfaces目标类是否有接口存在 且只有一个接口的时候接口类型是SpringProxy类型
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
    
    
			// 上面的三个方法有一个为true的话,则进入到这里
			// 从AdvisedSupport中获取被代理类
			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.");
			}
			// 判断目标类是否是接口 如果目标类是接口的话,则还是使用JDK的方式生成代理对象
			// 如果目标类是Proxy的子类或其实现类时,使用JDK动态代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    
    
				return new JdkDynamicAopProxy(config);
			}
			// 配置了使用Cglib进行动态代理或者目标类没有接口,那么使用Cglib的方式创建代理对象
			return new ObjenesisCglibAopProxy(config);
		}
		else {
    
    
			// 使用JDK的提供的代理方式生成代理对象
			return new JdkDynamicAopProxy(config);
		}
	}

JDK动态代理根Cglib动态代理在前面的文章中我们讲解过其源码实现过程,可以看这两篇文章进行学习,过程跟Spring AOP过程差不多。
《动态代理:Cglib原理讲解》
《动态代理:JDK动态代理源码学习》

总结

  1. 当切面类指定了proxy-target-class="true"属性时,代表要使用Cglib(proxyTargetClass属性会为true),此时有机会是Cglib代理。
  2. 条件1不满足时,看被代理类是否有preserverTargetClass属性,且值为true时,会将proxyTargetClass属性设置为true,此时有机会是Cglib代理。
  3. optimize为true时,此时有机会是Cglib代理。
  4. 被代理类只有一个接口,并且该接口是SpringProxy类型,此时有机会是Cglib代理。
  5. 被代理类没有实现接口,此时会将proxyTargetClass属性设置为true,此时有机会是Cglib代理。

以上5个条件满足其中1个,且被代理类不是接口或不是Proxy的子类或者实现类时使用Cglib代理。

因此,我们可以得出结论:

  • 被代理类没有接口时不一定使用Cglib进行代理,因为可能被代理类是一个接口或者是Proxy的子类或者实现类
  • 被代理类有接口时不一定使用JDK进行代理:
    • 有可能切面类指定了proxyTargetClass为true
    • 有可能被代理类的只有一个接口且是SpringProxy类型
    • 有可能代理工厂的optimize属性为true

猜你喜欢

转载自blog.csdn.net/weixin_45031612/article/details/128693145