前面几节的大部分都集中在spring的IOC部分,我们都知道spring的两大核心除了IOC之外还有AOP。aop的实现底层是动态代理,那么spring是如果实现这种动态代理,来达到aop的效果呢,这一节我们将揭开。
由于我们是在springboot中分析的,所以我们依然在springboot框架下分析。
我们找到@EnableAspectJAutoProxy注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
注意到这里import了一个AspectJAutoProxyRegistrar.class。熟悉spring注解驱动的都知道,这里会运行AspectJAutoProxyRegistrar#registerBeanDefinitions方法。
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);这行代码进入
直接跳到AopConfigUtils#registerOrEscalateApcAsRequired
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
//忽略
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
这里会在beanDefinitionMap中加入一个key是org.springframework.aop.config.internalAutoProxyCreator
value是AnnotationAwareAspectJAutoProxyCreator Definition的kv对
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
下面两步是把EnableAspectJAutoProxy注解中的proxyTargetClass和exposeProxy注解取来,如果是true,会做一些强制工作
下面我们要详细说AnnotationAwareAspectJAutoProxyCreator这个类,通过查看这个类的继承关系
注意到AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware 这里有一个SmartInstantiationAwareBeanPostProcessor和一个BeanFactoryaware我们之前也分析过BeanPostProcessor的作用,当然这里是SmartInstantiationAwareBeanPostProcessor,
先看BeanFactoryaware#setBeanFactory方法
这个方法在AbstractAdvisorAutoProxyCreator#setBeanFactory进行重写
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
} else {
this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
}
}
AnnotationAwareAspectJAutoProxyCreator#initBeanFactory
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder = new AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
这里做了两个动作,一个是创建aspectJ通知工厂,另一个动作是创建适配器
。接下去我们分析继承SmartInstantiationAwareBeanPostProcessor接口的原因
我们直接找到AbstractAutowireCapableBeanFactory的createBean方法,可以找到
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
还是那个面的注解就是返回一个代理对象。
aop的实际过程是在后置处理器的applyBeanPostProcessorsAfterInstantiation中
直接进入
AbstractAutoProxyCreator#applyBeanPostProcessorsAfterInstantiation
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
this.wrapIfNecessary这句话是关键点击进入句句分析
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null)
这里是获取到当前bean的所有增强器,也就是切面前后需要的方法,有一点值得主意的是都会有这个增强器
org.springframework.aop.interceptor.ExposeInvocationInterceptor.ADVISOR,这些增强器会加入到一个集合中
如果specificInterceptors(增强器集合不为空)就会创建代理对象,
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
我们进入createProxy
截取关键句分析
ProxyFactory proxyFactory = new ProxyFactory();这里创建一个代理工厂类,这个类是产生代理对象的关键
proxyFactory.addAdvisor(advisor); 这里把增强器的集合设置在proxyFactory中
proxyFactory.setTargetSource(targetSource) 把被增强的对象添加到工厂类中
return proxyFactory.getProxy(this.getProxyClassLoader());这句话是通过代理工厂来创建对象,我们进入这个方法
public Object getProxy(ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
这里createAopProxy有两个实现类,一个jdk的,一个是cglib的,两个区别在于,如果target对象是通过接口实现的,就通过jdk的实现类来创建代理对象,如果不是,则通过cglib的实现类来创建代理对象
贴上源代码
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
我们这里看JDK的动态代理
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
最后一句话Proxy.newProxyInstance就创建了目标类的一个代理类
此时我们就得到了一个增强后的代理类,其中也包括了增强器
这时候在spring容器的bean其实就是增强的代理bean,
当调用这个bean方法时候,实际上是调用这个代理bean。我们执行bean方法时候,先会调用
JdkDynamicAopProxy#invoke 方法
进入这个方法我们慢慢分析关键语句
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
这句话将会获得所有增强类的集合
这里用到了一个适配器模式,因为传入的是一个通知,适配成interceptor
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
这里会创建一个MethodInvocation,然后执行它的proceed()方法
Override
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
。。。。。。。
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这里有个递归的过程,((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);里面执行的也是proceed()方法
但是每次递归,索引都是自增一次,当自增到一定程度就会执行
return invokeJoinpoint();
如果五种通知并存,那么就会有这样的顺序
我们注意到MethodBeforeAdviceInterceptor中是这样的
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
说明这个会执行掉前置通知中的方法,然后再mi.proceed()
最终索引自增到一定程度然后执行
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
这时候目标类的方法会被执行
然后返回到上一层的after通知器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
执行invokeAdviceMethod,也就是后置处理
然后再执行return的通知器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
然后在执行throwing的通知器
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
这里如果没出现异常就不会到catch中,否则继续返回 mi.proceed();
最后再执行通用的ExposeInvocationInterceptor,
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
最终我们返回结果
ok,完工,这就是spring aop的完整原理!