大致流程主要分为三个步骤:
1: 创建AnnotationAwareAspectJAutoProxyCreator
对象
2: 扫描容器中的切面,创建PointcutAdvisor
对象
3: 生成代理类
创建AnnotationAwareAspectJAutoProxyCreator
对象
在配置类上面添加@EnableAspectJAutoProxy注解开启AOP,EnableAspectJAutoProxy类:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
EnableAspectJ?让我们的java程序支持AspectJ?其实是开启对AspectJ语法风格的支持
@Import(AspectJAutoProxyRegistrar.class):给容器导入AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
利用AspectJAutoProxyRegistrar来给容器注册注册了一个切面相关BeanDefinition
,正是上面提到的类:AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
该类的父类实现了SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware两个接口。结合IOC的流程来看,先是会注册BeanPostProcessor,保存在容器中,然后在bean的生命周期过程IOC 最后一个扩展方法postProcessAfterInitialization
中创建代理对象
SmartInstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation方法
SmartInstantiationAwareBeanPostProcessor会在创建Bean实例之前先尝试用postProcessBeforeInstantiation方法,做一些准备工作,比如判断当前Bean是否需要被代理,将通知方法封装成为增强器集合List<Advisor> candidateAdvisors等
postProcessAfterInitialization方法
真正发挥作用的是BeanPostProcessor.postProcessAfterInitialization方法,AnnotationAwareAspectJAutoProxyCreator的父类AbstractAdvisorAutoProxyCreator重写了BeanPostProcessor.postProcessAfterInitialization方法,所以实际执行的是:
@Override
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方法的逻辑:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 根据通知方法,创建拦截器数组
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;
}
creatProxy方法
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
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);
}
//自动判断用cglib动态代理或者是jdk动态代理生成代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
给容器返回增强了之后的代理对象,以后从容器中获取到的就是这个对象的代理对象,执行目标方法的时候,代理对象会去执行通知方法
拦截器链的执行流程
容器中保存了组件的代理对象,这个对象里面保存了详细信息(比如增强器,目标对象)如果没有拦截器链,直接执行目标方法,下面我们主要介绍有拦截器链的情况。
现在假设代理对象proxy调用了某个方法,那么这个方法会触发CglibAopProxy.intercept()方法,intercept()方法说穿了,就做了两件事:
①收集拦截器,做成链
②将需要执行的目标对象,目标方法,拦截器链等信息传入创建一个MethodInvocation对象,这对象可以理解为一个大杂烩。所有AOP功能所需要的的材料都在这里了,包括目标对象,拦截器链等,并调用MethodInvocation.proceed()方法,也就是拦截器链的触发过程,proceed方法就做了两件事:
①先执行全部的拦截器
②最后执行目标方法
public Object proceed() throws Throwable {
//如果拦截器链执行完毕了,那么直接调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//currentInterceptorIndex+1,执行拦截器的invoke方法
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
//
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
看到这里,可能会有疑问:既然拦截器都在目标方法之前执行,怎么实现AOP这种汉堡似的包夹调用顺序呢?我们来看看拦截器的invoke方法干了啥:
刚才说过了,拦截器是对增强器的包装,而我们的增强方法,Before/AfterReturning等等,所以拦截器肯定也有对应的Before/AfterReturning,我们先看看Before拦截器
@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
我们发现:
- 先调用了this.advice.before(),即反射执行@Before方法
- 再调用了MethodInvocation.proceed()方法
再来看看After拦截器
@SuppressWarnings("serial")
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
@Override
public boolean isBeforeAdvice() {
return false;
}
@Override
public boolean isAfterAdvice() {
return true;
}
}
- 先调用了MethodInvocation.proceed()方法
- 后反射调用了@After方法
Before和After拦截器有什么不一样?
Before拦截器是先反射调用@Before,再调用proceed方法
After拦截器是先调用proceed,再反射调用@AfterReturning方法
其实只有Before是特殊的,其他拦截器都是先调用proceed方法,再反射调用通知方法。
链式获取每个拦截器,拦截器执行invoke方法,每个拦截器等待下一个拦截器执行完了之后返回,拦截器链的机制,保证通知方法和目标方法的执行顺序。
总结
- @EnableAspectJAutoProxy开启AOP功能
- EnableAspectJAutoProxy会给容器注册一个AnnotationAwareAspectJAutoProxyCreator组件
- AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor
- 在IOC的流程中,当创建单例对象的时候,BeanPostProcessor的BeanPostProcessor的postProcessAfterInitialization方法会对此过程进行拦截,也就是说单例对象创建完成之后,判断该对象是否需要增强
- 如果判断需要被增强,那么将该对象的通知方法封装成为增强器,一个个的增强器再封装成为一个个的拦截器,形成一个拦截器链
- 将目标方法,拦截器链等信息传入创建一个MethodInvocation对象,调用MethodInvocation.proceed方法
- 利用拦截器的链式机制,最终的效果
正常执行:前置通知-》目标方法-》后置通知-》返回通知
异常执行:前置通知-》目标方法-》后置通知-》异常通知