本文基于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
这就很好的解释了一开始案例中代码执行顺序的问题