Spring 5.x 源码解析之详解AOP原理之生成代理
AOP代理是怎么生成
前面那篇只是对AOP做了简单的理解,希望能明白AOP具体做了什么,大致的原理是什么,本篇才是解释spring aop是怎么做到的,希望通过源码的方式来讲述整个过程,当然也是通过一个简单的例子啦。首先就先看看我们的简单例子的结构:
我们需要一个配置类AopConfig
,里面有一个服务,一个切面:
package com.aop;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
package com.aop;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.aop")
public class AopConfig {
public AopConfig(){
System.out.println("------AopConfig--------");
}
@Bean
public ServiceInterface getService(){
return new Service();
}
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
}
我们的服务很简单Service
:
package com.aop;
public class Service {
public Service(){
System.out.println("=======Service=======");
}
//业务方法
public int doService(int i) {
int result=5/i;
System.out.println("运行doService");
return result;
}
}
我们的切面是对服务打log:
package com.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
/*
* log切面类
* 通知:
* 前置 方法调用前@Before
* 后置 方法调用后@After
* 返回 方法返回后运行@AfterReturning
* 异常 方法出异常后@AfterThrowing
*/
@Aspect
public class LogAspects {
public LogAspects() {
System.out.println("======LogAspects========");
}
@Pointcut("execution(* com.aop.Service.*(..))")
public void pointCut() {
}
/**
* 在目标方法执行前
*/
@Before("pointCut()")
public void logStart(JoinPoint joinPoint) {
System.out.println("logStart 开始运行:" + joinPoint.getSignature().getName());
}
/**
* 在目标方法执行后
*/
@After("pointCut()")
public void logAfter() {
System.out.println("logAfter 结束运行");
}
/**
* 方法返回后
*/
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturning(Object result) {
System.out.println("logReturning 正常返回,结果:" + result);
}
/**
* 出现异常后
*/
@AfterThrowing(value = "pointCut()", throwing = "exception")
public void logException(Exception exception) {
System.out.println("logStarException 运行异常:" + exception);
}
}
最后是我们的测试类:
package com.aop;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class AopTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
Service service = applicationContext.getBean(Service.class);
System.out.println(service.doService(1));
}
}
代码先放着,我们先来说说执行的流程,先给一张主要的刷新流程图:
//刷新前预处理
// Prepare this context for refreshing.
prepareRefresh();
// 获取BeanFactory
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// BeanFactory预准备,属性赋值
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 自定义的子类实现
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// 执行BeanFactoryPostProcessors方法
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 注册后置处理器
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 标签国际化
// Initialize message source for this context.
initMessageSource();
// 初始化事件通知
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 自定义的刷新
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// 单例bean的实例化,不包括延迟加载
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
首先我们知道很多的操作都是由后置处理器来完成的,因为声明了@EnableAspectJAutoProxy
,
而这个注解类引入了AspectJAutoProxyRegistrar
,而且实现了ImportBeanDefinitionRegistrar
接口,就是在以后埋下的伏笔,才能有AspectJAwareAdvisorAutoProxyCreator
的定义:
然后在调用invokeBeanFactoryPostProcessors(beanFactory)
的时候,会进入调用ImportBeanDefinitionRegistrar
接口,从而进入AspectJAutoProxyRegistrar
调用registerBeanDefinitions
:
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
会定义AspectJAwareAdvisorAutoProxyCreator
然后我们就可以看到有那么多的Bean定义了,当然前面那步也或把Java配置类的@Bean
的工厂方法也定义进来:
但是还没有创建出来:
然后在继续往下走,registerBeanPostProcessors(beanFactory);
里会进行后置处理器的实例化,具体就不跟进去了:
然后继续走,一直走到finishBeanFactoryInitialization(beanFactory);
这里才是单例Bean的实例化的地方。我们拿前面定义的Service
类来讲,看他怎么实例化的,其实就是遍历我们的Bean定义,然后发现有工厂方法getService
,然后用反射去执行实例化,当然这之前肯定是先把配置类给实例化的:
可以看到,这个工厂方法调用其实是CGlib的代理对象。这个时候实例还是Service
,马上要进行初始化后置处理了,这个里面才会将他包装成代理对象:
就是AnnotationAwareAspectJAutoProxyCreator
这个后置处理器做的事:
最终我们的实例对象只是被当做代理工厂的目标源了:
会创建aop代理,然后获得代理:
里面就是创建JDK的还是CGLib的aop代理:
如果是JDK的话就调用,这个应该很熟悉吧:
否则就是CGLib,要做一大堆事,设置代理类,设置拦截器,设置通知方法等:
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
最后发现生成的已经不是Service
了,是CGLib的代理对象:
可以和前面对照:
这样我们的代理对象就有了,那我们的那些拦截器通知方法哪里来呢,其实也是finishBeanFactoryInitialization(beanFactory);
中的。在Java配置类的实例化之前,会有后置处理器AnnotationAwareAspectJAutoProxyCreator
处理,会去遍历所有的Bean名字定义,找出是切面的类,然后将里面的通知实例化后放缓存里:
其实很多地方细节都没讲到,因为不太好说,方法多,跳跃也多,讲了一些主要的地方,具体还是得自己去看比较好,我这里总结了个大致的图:
下一篇再来讲讲调用的时候是怎么进行的。好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵,部分图片来自网络,侵删。