spring aop源码分析代理创建过程

本文基于spring5.0.6,本文只关注aop相关的,其他内容跳过。先通过简单的案例,抛出遇到的问题

1. 案例

接口以及实现类
public interface AOPService {
    void doCom();
}
public class AOPServiceImpl implements AOPService {
    public void doCom() {
		System.out.println("执行");
	}
}
public class XmlTest {
    public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("com/devil/spring/aop/spring-aop.xml");
        AOPService service = context.getBean(AOPService.class);
        service.doCom();
    }
}
增强类
@Aspect
public class AopLog {
    @Pointcut("execution(* com.devil.spring.aop.AOPService.*(..))")
    public void init() {
        // 这里不执行
        System.out.println("AopLog init");
    }
    @Before(value = "init()")
    public void before() {
        System.out.println("before");
    }
    @After(value = "init()")
    public void after() {
        System.out.println("after");
    }
    @Around(value = "init()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("start around");
        pjp.proceed();
        System.out.println("end around");
    }
    @AfterReturning(value = "init()")
    public void afterReturning() {
        System.out.println("afterReturning");
    }
    @AfterThrowing(value = "init()")
    public void afterThrowing() {
        System.out.println("afterThrowing");
    }
}
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <!-- 开启aop自动扫描 -->
	<aop:aspectj-autoproxy />
	<!-- <aop:aspectj-autoproxy proxy-target-class="true" /> -->
	<!-- 用户服务对象 -->
	<bean id="AOPService" class="com.devil.spring.aop.AOPServiceImpl" />
</beans>
执行结果
start around
before
执行
end around
after
afterReturning

对于这个结果有点奇怪,为什么Around先于Before执行了,最后面会有解答。

2. 源码分析

2.1 注册BeanPostProcessor

进入ClassPathXmlApplicationContext的构造函数会发现调用了了refresh方法

public void refresh() throws BeansException, IllegalStateException {
	// ...... 
	// 注册后置处理器
	registerBeanPostProcessors(beanFactory);
	// 工厂初始化
	finishBeanFactoryInitialization(beanFactory);
	// ......
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
	// 从beanFactory工厂中获取所有的BeanPostProcessor的实现类类名
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
	// ......将各种BeanPostProcessor放入list
	// 根据优先级对后置处理器进行排序,并放入factory
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	// ...... 省略对不同类型的排序
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

这里可以通过断点看到 beanFactory 中的 BeanPostProcessor
在这里插入图片描述
在idea中点击xml的<aop:aspectj-autoproxy proxy-target-class=“true” /> 标签,可以看到AnnotationAwareAspectJAutoProxyCreator就是标签对应的类。

2.2 创建bean

回到refresh中调用的finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// ......
	// 准备所有剩余(非懒加载)的单例
	beanFactory.preInstantiateSingletons();
}

DefaultListableBeanFactory.preInstantiateSingletons

public void preInstantiateSingletons() throws BeansException {
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	// 下面主要是遍历beanNames来创建bean,重点就是getBean方法
	for (String beanName : beanNames) {
		// ......
		getBean(beanName);
	}
	// ......
}

来看看getBean相关,省略其余代码

public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
	final String beanName = transformedBeanName(name);
	Object bean;
	Object sharedInstance = getSingleton(beanName);
	// getSingleton会从缓存获取,缓存中有了
	if (sharedInstance != null && args == null) {
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
	// 缓存中没有就要创建
	else {
		// ......
		// 获取bean的描述类--RootBeanDefinition
		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		// ...... 解决依赖问题
		// scope = singleton 单一实例
		if (mbd.isSingleton()) {
			sharedInstance = getSingleton(beanName, () -> {
				return createBean(beanName, mbd, args);
			});
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
		}
		// scope = prototype 容器每次返回新的实例,不保存下来对其进行管理
		else if (mbd.isPrototype()) {
			// ...... 也会走createBean
		}
		// scope 为其他 如request、session、globalsession
		else {
			// ...... 也会走createBean
		}
	}
	// ......
	return (T) bean;
}

主要看createBean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	RootBeanDefinition mbdToUse = mbd;

	// 根据名称和对应数据结构解析出类对象
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// 准备 method overrides 复写
	mbdToUse.prepareMethodOverrides();
	// 给 InstantiationAwareBeanPostProcessor 返回代理类替代目标bean实例的机会(当有TargetSource实现)
	// 注意:之前看到里面有创建代理的代码,就以为平常的逻辑也有这里,其实不是
	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
	if (bean != null) {
		return bean;
	}
	// 重点来了:创建bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
	return beanInstance;
}

2.3 创建Proxy代理类

既然创建代理,这里肯定使用了代理模式,aop中主要使用的是动态代理。中间省略一些代码片段,直接在AbstractAutowireProxyCreator.createProxy里面打断点,调用栈如下:
在这里插入图片描述
AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization方法

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {
	Object result = existingBean;
	// 获取 BeanPostProcessor 调用对应的 postProcessAfterInitialization 方法
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

来到 AbstractAutoProxyCreator 类 (实现了BeanPostProcessor)

public Object postProcessAfterInitialization(@Nullable 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;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 终于来了....如果目标bean有advice通知,则创建代理类
	// specificInterceptors 是拦截当前 bean 的 advisor、advice、interceptor
	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;
	}
	// 放入缓存
	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

createProxy

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);
	}
	// 创建ProxyFactory
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);
	// 在xml中配置proxy-target-class="true",将都使用 CGLIB 来代理
	if (!proxyFactory.isProxyTargetClass()) {
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		} else {
			// 点进去稍微看一下代码就知道了,主要就两句:
         // 1. 有接口的,调用一次或多次:proxyFactory.addInterface(ifc);
	         // 2. 没有接口的,调用:proxyFactory.setProxyTargetClass(true);
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
	// 将specificInterceptors转为advisors
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);
	
	// ......
	return proxyFactory.getProxy(getProxyClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

createAopProxy在ProxyCreatorSupport中实现

public class ProxyCreatorSupport extends AdvisedSupport {

	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}	
	
	public AopProxyFactory getAopProxyFactory() {
		return this.aopProxyFactory;
	}
	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}
}

可以知道将调用 DefaultAopProxyFactory 的createAopProxy方法

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// config.isProxyTargetClass就是上面说的和cglib有关的配置
	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);
	}
}

可以看到如果如果实现接口,使用 JDK 动态代理。如果没有实现任何接口或者设置了 proxy-target-class=“true”,会使用 CGLIB 实现代理。
JDK 动态代理基于接口,所以只有接口中的方法会被增强,而 CGLIB 基于类继承,需要注意就是如果方法使用了 final 修饰,或者是 private 方法,是不能被增强的。
cglib就先不看了主要看jdk动态代理的,有关jdk动态代理的可以看 源码解析JDK动态代理原理
主要是看调用的getProxy方法

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
	}
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 返回一个代理类
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
}

到此代理类的生成就结束了

3. 调用增强

由于JdkDynamicAopProxy实现InvocationHandler,当我们调用方法的时候,会执行invoke方法(每次调用bean的代理类被增强的方法都会调用invoke)

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Object target = null;
	
	// ......对equalse hashcode等的处理
	Object retVal;
	if (this.advised.exposeProxy) {
		// 如果设置了 exposeProxy,那么将 proxy 放到 ThreadLocal 中
		oldProxy = AopContext.setCurrentProxy(proxy);
		setProxyContext = true;
	}
	target = targetSource.getTarget();
	Class<?> targetClass = (target != null ? target.getClass() : null);
	// 创建一个 chain,包含所有要执行的 advice
	List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
	if (chain.isEmpty()) {
		Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
		// 如果是没有增强,直接调用原来的方法
		retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
	} else {
		// invocation如下图所示
		invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
		// 执行增强,获取返回结果
		retVal = invocation.proceed();
	}
	// ......
	return retVal;
	// ......
}

这里使用了责任链模式,chain中的顺序如下:AfterThrowing -> AfterReturning ->After -> Around ->Before
在这里插入图片描述

继续代码可以看到invocation中有对应增强的方法,来看看ReflectiveMethodInvocation的proceed方法

public Object proceed() throws Throwable {
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		// 在这里的时候,调用列表已经结束,执行原来的方法
		return invokeJoinpoint();
	}
	// 增加currentInterceptorIndex计数,从interceptorsAndDynamicMethodMatchers获取增强方法
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// ......这里不研究了,应该是特殊处理,断点走下面的
	} else {
		// 调用对应的增强方法
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

interceptorsAndDynamicMethodMatchers中存放顺序如下

@AfterThrowing 抛出异常后
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		} catch (Throwable ex) {
			// 是否是指定的方法 执行对应的AfterThrowing方法
			if (shouldInvokeOnThrowing(ex)) {
				invokeAdviceMethod(getJoinPointMatch(), null, ex);
			}
			throw ex;
		}
	}
}
@AfterReturning 方法返回后
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

	private final AfterReturningAdvice advice; // AspectJAfterReturningAdvice

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		// 先执行目标方法
		Object retVal = mi.proceed();
		// 执行afterReturn的方法
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}

}
@After 方法执行完之后,不管有没有抛出异常
public class AspectJAfterAdvice extends AbstractAspectJAdvice
		implements MethodInterceptor, AfterAdvice, Serializable {
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			// 回到上面,对方法做下个增强方法
			return mi.proceed();
		} finally {
			// 执行after
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
}
@Around 方法前后都执行
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
	public Object invoke(MethodInvocation mi) throws Throwable {
		if (!(mi instanceof ProxyMethodInvocation)) {
			throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
		}
		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
		JoinPointMatch jpm = getJoinPointMatch(pmi);
		// 直接调用Around增强的方法,由于在interceptorsAndDynamicMethodMatchers中的位置先于MethodBeforeAdviceInterceptor
		// 所以会先进入Around增强的方法,在其方法中执行pjp.proceed()后再调用列表中的Before增强,结束后回到Around方法
		return invokeAdviceMethod(pjp, jpm, null, null);
	}
}
@Before 方法执行之前
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

	private MethodBeforeAdvice advice; // AspectJMethodBeforeAdvice

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		// 执行before的方法
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		// 回到上面,对方法做下个增强方法
		return mi.proceed();
	}
}

由上面图片可以知道,Around方法会先于Before执行,所以正常情况下,方法执行顺序如下:
around -> before -> 执行 -> around -> after -> after return
而当执行中出现异常后,会有如下顺序:
around -> before -> 执行 -> around -> after -> after thrown

这就很好的解释了一开始案例中代码执行顺序的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值