@EnableAspectJAutoProxy 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
// 使用CGLIB代理
boolean proxyTargetClass() default false;
// 是否暴露代理对象
boolean exposeProxy() default false;
}
在这个注解中引入AspectJAutoProxyRegistrar,它是ImportBeanDefinitionRegistrar接口的实现。
ImportBeanDefinitionRegistrar接口和ImportSelector接口是Spring中两个扩展接口,分别通过registerBeanDefinitions方法和selectImports方法向容器注入Bean。
AspectJAutoProxyRegistrar的registerBeanDefinitions方法:
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
// proxyTargetClass:true强制使用CGLIB代理
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 是否暴露代理对象
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
1、进入AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法会发现这个方法将一个类AnnotationAwareAspectJAutoProxyCreator注册到了容器中。
2、proxyTargetClass=true则强制使用CGLIB代理,否则会根据目标类是否实现了接口,自动选择是JDK代理或者是CGLIB代理。
3、有时候目标对象内部的自我调用无法实施切面中增强exposeProxy=true会将代理对象暴漏到AopContext中,此时使用AopContext.currentProxy即可。
AOP切入点
AnnotationAwareAspectJAutoProxyCreator类的继承关系为:
BeanPostProcessor
|
SmartInstantiationAwareB
|
AbstractAutoProxyCreator
|
AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator是BeanPostProcessor接口的实现。
BeanPostProcessor这个接口Spring中一个特殊且重要的接口,会在容器实例化Bean的时候调用,调用不止一次,比如会在实例化前,实例化后,属性填充后等等适合的时机调用BeanPostProcessor的实现。具体参见spring容器加载分析 一容器构造。
大致梳理下Bean的实例化过程:
在AbstractAutowireCapableBeanFactory类中有具体的Bean实例化方法doCreateBean:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
1: 实例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
2: 是否需要提早曝光:单例&允许循环依赖&当前bean增在创建中,检查循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
3: 对bean的各种属性进行填充,有可能依赖其他bean,递归初始化 step4.2.3
4: 调用初始化方法init-method、此处也有机会返回Bean的代理对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
5: 解决循环依赖
return exposedObject;
}
进入initializeBean方法:
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
1:如果Bean有InitMethod开始调用
invokeInitMethods(beanName, wrappedBean, mbd);
2: 调用BeanPostProcessors的postProcessBeforeInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
3: 调用BeanPostProcessors的postProcessAfterInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
// 如果启用了AOP此处应该返回了代理对象,也就是说原来初始化的bean被替换了。
return wrappedBean;
}
AOP生成代理的切入点就在applyBeanPostProcessorsAfterInitialization方法中了,遍历BeanPostProcessor列表然后依次调用postProcessAfterInitialization方法,AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法中正好返回了Bean的代理对象,则代理对象在doCreateBean方法中替换掉了原生的Bean实例。
代理对象生成和切面织入过程
postProcessAfterInitialization方法的实现:
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;
}
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;
}
//判断给定的BEAN是否是一个基础设施类 ,基础设施类不应代理或者配置了指定的BEAN不需要代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果目标类存在advice则创建代理.
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;
}
只有存在advice(增强)的Bean才会创建代理,getAdvicesAndAdvisorsForBean就是获取绑定到Bean上的advice列表,如果列表为空则不创建代理。
获取advice列表在类AnnotationAwareAspectJAutoProxyCreator中。
protected List<Advisor> findCandidateAdvisors() {
// 调用父类的方法去查找Advisors,查找所有实现了org.springframework.aop.Advisor接口的BEAN
// 主要是为了不遗漏XML配置的advisors
List<Advisor> advisors = super.findCandidateAdvisors();
// AspectJ注解的Advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
第一步先获取实现了Advisor接口的Bean,使用BeanFactoryUtils.beanNamesForTypeIncludingAncestors方法。
第二步获取有@Aspect注解的Bean,委托给了BeanFactoryAspectJAdvisorsBuilder类,解析方法buildAspectJAdvisors()处理过程如下:
1:获取所有的beanNames,再由beanFactory.getType(beanName)获取Bean的class列表
2:判断是否包含@Aspect注解
3:解析成Advisor列表
4:使用AopUtils.findAdvisorsThatCanApply检查Advisor与Bean是否匹配,过滤掉不匹配的Advisor。
如果Advisor列表不为空则进入代理创建逻辑,
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);
//判定给定的bean是否代理Class
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}else {
// 评估解析代理的接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 添加Advisors
proxyFactory.addAdvisors(advisors);
// 设置目标类
proxyFactory.setTargetSource(targetSource);
// 定制代理
customizeProxyFactory(proxyFactory);
// 设置是否冻结,默认为false即代理设置后不允许修改代理的配置
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
ProxyFactory中委托DefaultAopProxyFactory类来确定Bean的代理类型
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 对生成代理策略进行优化||强制使用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.");
}
// 目标类为接口,JDK代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// CGLIB代理
return new ObjenesisCglibAopProxy(config);
} else {
// JDK代理
return new JdkDynamicAopProxy(config);
}
}
此时已经确定了Bean是使用JDK代理还是使用CGLIB代理,JDK代理使用
JdkDynamicAopProxy来生成代理类、CGLIB代理使用ObjenesisCglibAopProxy来生成代理类。
ObjenesisCglibAopProxy代理类的生成过程:
public Object getProxy(ClassLoader classLoader) {
try {
// 目标对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
// 目标对象是否是CGLIB的代理对象
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 验证类,主要是验证final方法
validateClassIfNecessary(proxySuperClass, classLoader);
// CGLIB的增强器
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 ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 获取类的回调列表,都是MethodInterceptor的实例
// 最主要的DynamicAdvisedInterceptor,这个就是动态织入增强的拦截器
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
return createProxyClassAndInstance(enhancer, callbacks);
}
}
这个方法就是创建代理的核心方法,主要是获取目标对象,获取类的回调列表,这个回调列表都是MethodInterceptor的实例,可以看成是方法的拦截器链。其中最主要的是DynamicAdvisedInterceptor,这个Interceptor为Bean的切点方法进行Advisor动态织入。
// proxy 代理对象 、method 目标类方法 、args 方法参数、 methodProxy 每个被代理的方法都对应一个MethodProxy对象
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 目标对象
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果没有拦截器链,则直接调用目标类的方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 返回目标对象的调用结果
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 构造CglibMethodInvocation,递归调用拦截器链
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 返回实施增强之后的调用结果
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
}
intercept就是拦截代理类的方法,匹配切入点,如果方法可以切入则根据切入逻辑依次执行增强逻辑,如果不匹配切入点则直接执行目标类的方法,切入点匹配逻辑在DefaultAdvisorChainFactory类中实现。
码字不易,转载请保留原文连接[https://www.jianshu.com/p/f504afb066f9)