aop:面向切面编程,把与核心业务逻辑无关的代码全部抽取出来,放置到某个地方集中管理,然后在具体运行时,再由容器动态织入这些共有代码
1 spring aop使用
注意:spring aop使用部分以普通的spring应用为例。(非springboot应用)
maven依赖
spring应用:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.18.RELEASE</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.18.RELEASE</version>
</dependency>
springboot应用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.2.11.RELEASE</version>
</dependency>
1.1 开启spring aop
1.1.1 spring应用开启aop(注解版)
使用ssm框架的项目就是spring应用(区别于springboot)
配置类上加@EnableAspectJAutoProxy注解开启aop
//开启spring aop
@EnableAspectJAutoProxy
@Configuration
public class AopConfiguration {
}
1.1.2 springboot应用开启sop
springboot应用默认就开启了aop。spring-boot-autoconfigure模块类路径下META-INF/spring.factories文件引入了AopAutoConfiguration自动配置类,AopAutoConfiguration类中使用了@EnableAspectJAutoProxy注解。
1.2 编写切面类
/**
* 切面类
*/
@Aspect
public class LogAspects {
/**
* 抽取公共的切入点表达式
* 1、本类引用
* 2、其他类引用
*/
@Pointcut("execution(public int com.dyzwj.aop.MathCalculator.div(..))")
public void pointcut(){}
@Before("pointcut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+ Arrays.asList(args)+"}");
}
//外类引用
@After("com.dyzwj.aop.LogAspects.pointcut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value = "pointcut()",returning = "result")
public void logReturn(JoinPoint joinPoint, Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value = "pointcut()",throwing = "exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
1.3 业务逻辑代码(目标类)
//业务逻辑类 目标类
public class MathCalculator {
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
//思考:结合切面类的切点表达式的配置,调用aa()方法会不会触发切面逻辑?不会
public void aa(int i,int j){
// System.out.println(this);
this.div(i,j);
}
}
1.4 配置
//显示开启spring aop
@EnableAspectJAutoProxy
@Configuration
public class AopConfiguration {
//业务逻辑类加入到容器中
@Bean
public MathCalculator mathCalculator(){
return new MathCalculator();
}
//切面类加入到容器中
@Bean
public LogAspects logAspects(){
return new LogAspects();
}
@Bean
public AA aa(){
return new AA();
}
}
1.5执行目标方法
public class AopMain {
public static void main(String[] args) {
//手动创建注解版的容器
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AopConfiguration.class);
MathCalculator bean = annotationConfigApplicationContext.getBean(MathCalculator.class);
// System.out.println(bean);
// System.out.println(AopUtils.isAopProxy(bean));
//bean.aa(10,2);
//System.out.println();
bean.div(10,2);
// AA bean = annotationConfigApplicationContext.getBean(AA.class);
// bean.bb(10,2);
}
}
2 spring aop原理
源码版本说明
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.18.RELEASE</version>
</dependency>
spring支持的代理方式:
-
jdk动态代理
-
cglib代理
2.1 @EnableAspectJAutoProxy注解
//类上使用@Import注解导入了AspectJAutoProxyRegistrar,该类实现了ImportBeanDefinitionRegistrar接口,重写了registerBeanDefinitions()方法
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
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) {
//注册beanDefinition == AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
public abstract class AopConfigUtils {
/**
* The bean name of the internally managed auto-proxy creator.
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果当前注册器包含internalAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {//如果当前类不是internalAutoProxyCreator
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {//如果下标大于已存在的内部自动代理构造器,index越小,优先级越高
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
//如果当前注册器不包含internalAutoProxyCreator,则把当前类作为根定义
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
}
AspectJAutoProxyRegistrar#registerBeanDefinitions给容器中注册了bean id为internalAutoProxyCreator ==> AnnotationAwareAspectJAutoProxyCreator类型的bean
2.2 AnnotationAwareAspectJAutoProxyCreator
/**
*
*概述
* 1、获取当前应用上下文中所有使用@AspectJ注解的切面类中的advice方法和所有Spring Advisor bean;
* 获取所有advice方法/advisor的任务在AnnotationAwareAspectJAutoProxyCreator应用到每个bean创建时执行,但内部使用了缓存机制,所以真正的查找过程只发生在第一次被调用时。
*
* 2、在每个bean创建时检测该bean是否符合创建代理的条件,如果符合,则获取可以应用在该bean上的所有advise,为当前bean生成一个代理对象。
* 是否符合条件的主要判断逻辑为AopUtils#findAdvisorsThatCanApply
*/
@SuppressWarnings("serial")
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
@Nullable
private List<Pattern> includePatterns;
@Nullable
private AspectJAdvisorFactory aspectJAdvisorFactory;
@Nullable
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 使用基类方法初始化 beanFactory,真正的逻辑时构造一个能够从容器中获取所有
super.initBeanFactory(beanFactory);
// 下面的逻辑是构造 aspectJAdvisorsBuilder , 用于通过反射方法从容器中获取
// 所有带有@AspectJ注解的 beans
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
// 找到容器中所有的Spring Advisor beans 和 @AspectJ 注解的 beans,都封装成
// Advisor 形式返回一个列表
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
/**
* 使用基类Spring Advisor查找机制查找容器中所有的Spring Advisor
* 其实就是父类使用所构造的BeanFactoryAdvisorRetrievalHelper从
* 容器中获取所有的Spring Advisor beans。
*/
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
/**
* 使用aspectJAdvisorsBuilder从容器中获取所有@AspectJ 注解的bean,并将它们包装成Advisor
*/
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
// 现在列表advisors包含容器中所有的Spring Advisor beans 和 @AspectJ 注解的 beans,
// 现在它们都以 Advisor 的形式存在
return advisors;
}
// 判断指定的类是否是一个基础设置类:
// 1. 如果父类的 isInfrastructureClass 断定它是一个基础设施类,就认为它是;
// 2. 如果这是一个@Aspect注解的类,也认为这是一个基础设施类;
// 一旦某个bean类被认为是基础设施类,那么将不会对该类实施代理机制
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
}
看下AnnotationAwareAspectJAutoProxyCreator的继承结构
AnnotationAwareAspectJAutoProxyCreator extends
AspectJAwareAdvisorAutoProxyCreator extends
AbstractAdvisorAutoProxyCreator extends
AbstractAdvisorAutoProxyCreator extends
AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
从AnnotationAwareAspectJAutoProxyCreator的继承结构看,主要关注后置处理器(SmartInstantiationAwareBeanPostProcessor:bean初始化前后)和自动装配BeanFactory的逻辑。
2.3 自动装配BeanFactory
AbstractAutoProxyCreator.setBeanFactory():实现BeanFactoryAware接口的setBeanFactory方法
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
private BeanFactory beanFactory;
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
AbstractAdvisorAutoProxyCreator.setBeanFactory():重写 -> super.setBeanFactory(); -> initBeanFactory(beanFactory);
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
// 覆盖基类的setBeanFactory方法
@Override
public void setBeanFactory(BeanFactory beanFactory) {
// 首先调用基类的setBeanFactory方法
super.setBeanFactory(beanFactory);
// 要求所设置的 beanFactory 也就是Spring bean容器必须使用类型 ConfigurableListableBeanFactory,
// 否则抛出异常,声明当前 AdvisorAutoProxyCreator 只针对类型为 ConfigurableListableBeanFactory
// 的容器工作
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
// 上面设置完beanFactory检查过类型之后,立即初始化 beanFactory
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
// 初始化 beanFactory,初始化逻辑 :
// 准备一个针对该beanFactory的BeanFactoryAdvisorRetrievalHelperAdapter赋值给this.advisorRetrievalHelper, 用于从beanFactory获取Spring Advisor(即通知)
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 初始化从容器中获取符合条件的 Spring Advisor
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
}
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory():重写
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 使用基类方法初始化 beanFactory,真正的逻辑时构造一个能够从容器中获取所有
super.initBeanFactory(beanFactory);
// 下面的逻辑是构造 aspectJAdvisorsBuilder , 用于通过反射方法从容器中获取
// 所有带有@AspectJ注解的 beans
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
}
自动装配BeanFactory主要做了两件事:
-
初始化BeanFactoryAdvisorRetrievalHelperAdapter:从beanFactory获取Spring Advisor(即通知)
-
初始化BeanFactoryAspectJAdvisorsBuilderAdapter:通过反射从容器中获取所有带有@AspectJ注解的 bean
2.4 spring bean的生命周期
(1)创建(包括属性赋值):
- 单实例 容器启动的时候创建对象
- 多实例 每次获取的时候创建对象
(2)BeanPostProcessor.postProcessBeforeInitialization
(3)初始化:对象创建完成,并赋好值,调用初始化方法
(4)BeanPostProcessor.postProcessAfterInitialization
(5)销毁:
- 单实例 容器关闭的时候
- 多实例 容器不会管理多实例bean,不会调用销毁方法
何为初始化?
spring支持的bean的初始化方式:
(1) @Bean(initMethod,destroyMethod);
(2) 通过让bean实现InitializingBean定义初始化逻辑,实现DisposableBean定义销毁逻辑(代码有侵入)
注:Spring不推荐使用InitializationBean 来调用其初始化方法,因为它不必要地将代码耦合到Spring
(3) 使用JSR250规范提供的注解:spring中提供了CommonAnnotationBeanPostProcessor负责支持@PostConstruct和@PreDestroy
- @PostConstruct:在bean创建并完成属性赋值后,执行初始化逻辑
- @PreDestroy:在容器销毁bean之前执行销毁逻辑
既然支持多种初始化方式,那么这几种初始化方式的顺序是什么样的?
-
@PostConstruct
-
InitializingBean
-
@Bean(initMethod)
2.5 后置处理器逻辑
其实spring的BeanPostProcessor贯穿spring bean的生命周期(BeanPostProcessor还有许多子接口)。主要作用有:
- 推断构造方法
- 为循环依赖做准备
- 属性注入
- aop
现在来看@EnableAspectJAutoProxy给容器中导入的bean-AnnotationAwareAspectJAutoProxyCreator。
看框中的部分,其父类AbstractAutoProxyCreator实现了BeanPostProcessor接口的postProcessAfterInitialization方法,在该方法中,会判断是否需要对bean进行包装(即代理)。
AbstractAutoProxyCreator#wrapIfNecessary源码阅读建议:先把代理的整体的流程弄清楚,再去查看子类实现的细节,比如getAdvicesAndAdvisorsForBean方法,最后自己跟着源码走一遍
2.5.1 是否需要进行代理
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
/**
* earlyProxyReferences.remove(cacheKey) != bean为true 表示bean还没有进行aop
* 在处理循环依赖时,有些bean提前完成了aop,会放到earlyProxyReferences集合中,因为已经进行了aop,所以此时就不需要进行aop了
* 一般的bean在执行到此处时,不会再earlyProxyReferences结合中 所以都会进入此分支
*/
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
///如果是用户自定义获取实例,不需要增强处理,直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 查询map缓存,标记过false,不需要增强直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 判断一遍springAOP基础构建类或需要跳过的,标记为false,不需要增强直接返回
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
/**
* // 获取针对该bean的所有专用拦截器对象,对返回值数组需要分三种情况考虑 :
* // 1. 返回数组有值 : 需要做代理,使用专用拦截器和通用拦截器
* // 2. 返回数组无值,为空 : 需要做代理,仅使用通用拦截器
* // 3. 返回为null : 不要给当前 bean 做代理
* // 当前类 getAdvicesAndAdvisorsForBean 方法其实是一个抽象方法,具体实现由实现子类提供
*/
//获取当前bean的所有候选增强器(即当前bean符合切点表达式的)
//AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果存在增强器
if (specificInterceptors != DO_NOT_PROXY) {
//把当前bean保存在增强过的bean集合advisedBeans中 // 标记增强为TRUE,表示需要增强实现
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//创建当前bean的代理对象 生成增强代理类
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
//保存在proxyType中
this.proxyTypes.put(cacheKey, proxy.getClass());
//给容器中返回当前组件使用cglib增强了的代理对象
//以后从容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程
return proxy;
}
// 如果不存在增强,标记false,作为缓存,再次进入提高效率
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 如果是ConfigurableListableBeanFactory接口(咱们DefaultListableBeanFactory就是该接口的实现类)则,暴露目标类
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
//给beanFactory->beanDefinition定义一个属性:k=AutoProxyUtils.originalTargetClass,v=需要被代理的bean class
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
//复制配置信息
proxyFactory.copyFrom(this);
//如果不是代理目标类
if (!proxyFactory.isProxyTargetClass()) {//如果beanFactory定义了代理目标类(CGLIB)
if (shouldProxyTargetClass(beanClass, beanName)) {//代理工厂设置代理目标类
proxyFactory.setProxyTargetClass(true);
}
else {//否则设置代理接口(JDK)
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 将针对当前 bean 的所有的专用拦截器和容器中的通用拦截器一并包装成 Spring Advisor 对象
// 用于创建最终的代理对象
// 构建最终适用于该bean的所有Advisor拦截器:
// 1. 从容器获取通用拦截器
// 2. 加上仅仅适用于该bean的专用拦截器 : specificInterceptors
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//将advisors保存到proxyFactory中
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 定制化 proxyFactory, 方法#customizeProxyFactory在本类是一个空方法,
// 这里主要是留给实现子类一个定制 proxyFactory 的机会
customizeProxyFactory(proxyFactory);//空方法,留给子类拓展用
//用于控制代理工厂是否还允许再次添加通知,默认为false(表示不允许)
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {//默认false,上面已经前置过滤了匹配的增强Advisor
proxyFactory.setPreFiltered(true);
}
//创建代理对象,spring自动决定
//ProxyFactory.getProxy()
return proxyFactory.getProxy(getProxyClassLoader());
}
//AnnotationAwareAspectJAutoProxyCreator#isInfrastructureClass重写了该方法
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
//AspectJAwareAdvisorAutoProxyCreator#shouldSkip重写了该方法
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
}
2.5.2 代理逻辑
AbstractAdvisorAutoProxyCreator
/**
* AbstractAdvisorAutoProxyCreator自身实现了基类定义的抽象方法#getAdvicesAndAdvisorsForBean()用于从容器中获取针对某个bean可用的AOP Advice和Spring Advisor bean。
* 并且AbstractAdvisorAutoProxyCreator对#getAdvicesAndAdvisorsForBean()的实现只使用容器中的Spring Advisor,而不考虑AOP Advice。
AbstractAdvisorAutoProxyCreator约定一个bean需要被自动代理的条件是:容器中存在至少一个跟该bean匹配的Spring Advisors。这里一个bean跟容器中某个Spring Advisor bean是否匹配的匹配逻辑如下 :
1、AbstractAdvisorAutoProxyCreator自身提供一个方法boolean isEligibleAdvisorBean(String beanName)来根据Advisor bean名称声明该Advisor是否符合条件(此方法的缺省实现为总是返回true,子类可以覆盖实现该方法),当前APC工作时会首先从容其中筛选出所有符合该条件的Spring Advisors作为候选;
2、从上面的Spring Advisors候选中,利用bean类/方法上的注解信息再次筛选,选出那些跟当前bean匹配的Spring Advisors作为最终要包裹到当前bean的Spring Advisors。
有顺序要求的Spring Advisor可以实现接口org.springframework.core.Ordered接口,因为AbstractAdvisorAutoProxyCreator会对符合条件的Spring Advisor做相应的排序然后才包裹到目标bean上。
*/
@SuppressWarnings("serial")
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
@Nullable
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
// 覆盖基类的setBeanFactory方法
@Override
public void setBeanFactory(BeanFactory beanFactory) {
// 首先调用基类的setBeanFactory方法
super.setBeanFactory(beanFactory);
// 要求所设置的 beanFactory 也就是Spring bean容器必须使用类型 ConfigurableListableBeanFactory,
// 否则抛出异常,声明当前 AdvisorAutoProxyCreator 只针对类型为 ConfigurableListableBeanFactory
// 的容器工作
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
// 上面设置完beanFactory检查过类型之后,立即初始化 beanFactory
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
/**
* // 准备一个针对该beanFactory的BeanFactoryAdvisorRetrievalHelperAdapter赋值给this.advisorRetrievalHelper,
* 用于从beanFactory获取Spring Advisor(即通知)。
*/
// 初始化从容器中获取符合条件的 Spring Advisor
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
// 找到针对某个bean的所有符合条件的Advisor/Advice,如果结果为null,将不会为该bean创建代理
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取容器中所有针对 beanClass,beanName 可用的 Spring Advisors
//找到合格的增强器(适用于当前bean的 即当前bean符合切点表达式的)
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
// 如果一个可用的 Spring Advisor 都没有找到则返回 null,表示不要给当前bean创建代理
// DO_NOT_PROXY 其实是一个为 null 的常量,用于表示:
// 如果找不到符合条件的Advisor,就不要为该bean创建代理
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到所有候选的增强器
// 从容器中找到所有的 Spring Advisors bean 组件作为候选,此结果尚未针对当前 bean 进行筛选
// 当前类中方法 #findCandidateAdvisors() 是一个抽象方法,要求由子类提供实现
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 将每个候选 Spring Advisor 针对当前 bean 进行筛选,留下符合条件的
//从中找到能适用在当前bean的增强器
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 对符合条件的 Spring Advisors 列表做扩展,当前类的该实现方法为空实现,
// 子实现类可以重写该方法做相应的扩展
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//给增强器排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
//在容器中找advisor
return this.advisorRetrievalHelper.findAdvisorBeans();
}
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
// ProxyCreationContext 使用了一个 ThreadLocal 变量保持当前正在进行代理创建的bean,
// 在代理创建过程中,比如对pointcut表达式求值时会使用到 ProxyCreationContext,
// 由此可见,某个bean的代理创建必须在同一个线程内完成,不能跨线程
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//找可以使用的增强器
// 具体检查每个advisor是否需要应用到该bean的逻辑委托给AopUtils完成,这里不做深入分析,
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
// 已经完成advisor和bean的匹配过程,清除ProxyCreationContext
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
/**
* Return whether the Advisor bean with the given name is eligible
* for proxying in the first place.
* @param beanName the name of the Advisor bean
* @return whether the bean is eligible
*/
protected boolean isEligibleAdvisorBean(String beanName) {
return true;
}
}
ProxyFactory
public class ProxyFactory extends ProxyCreatorSupport {
public Object getProxy(@Nullable ClassLoader classLoader) {
//JdkDynamicAopProxy:jdk动态代理 -> 实现了接口
//ObjenesisCglibAopProxy:cglib动态代理 -> 未实现接口
return createAopProxy().getProxy(classLoader);
}
}
AdvisedSupport
public class ProxyCreatorSupport extends AdvisedSupport {
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//决定使用jdk动态代理还是cglib代理
//DefaultAopProxyFactory#createAopProxy
return getAopProxyFactory().createAopProxy(this);
}
}
2.5.3 采用哪种代理方式
DefaultAopProxyFactory:aop代理工厂,决定目标对象采用jdk动态代理或cglib代理
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
}
CglibAopProxy:cglib创建代理
class CglibAopProxy implements AopProxy, Serializable {
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 (ClassUtils.isCglibProxyClass(rootClass)) {
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 ClassLoaderAwareUndeclaredThrowableStrategy(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);
}
}
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
// 对 expose-proxy 属性的处理
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
/**
* 将拦截器封装在 DynamicAdvisedInterceptor 中
*
* 链式调用
*/
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
//主回调
Callback[] mainCallbacks = new Callback[] {
// 将拦截器链加入 Callback 中
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
/**
* 遍历类中的所有方法
*/
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
/**
* 获取每个方法对应的拦截器链
*/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods.toString(), x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
/**
* 根据主回调和
*/
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
//cglib创建代理对象的方式,感兴趣的可以研究一下
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
}
JdkDynamicAopProxy:jdk动态代理
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
/**
* this(JdkDynamicAopProxy)就是一个InvocationHandler对象 目标对象执行时,会调用到InvocationHandler.invoke()方法
*/
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
/**
* 获取拦截器链
*/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
/**
* 如果拦截器链为空 直接执行目标方法
*/
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
/**
* 如果有拦截器链,把需要执行的目标对象、目标方法、拦截器链等信息创建一个CglibMethodInvocation,
* 并调用proceed()方法触发拦截器链和目标方法调用
*/
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
可以看到,无论是cglib代理还是jdk动态代理,都是将代理逻辑封装成拦截器链(责任链模式),而且拦截器链中的第一个拦截器是DynamicAdvisedInterceptor,因此,目标方法执行时,实际上会执行到拦截器链的中拦截器MethodInterceptor.invoke方法,即DynamicAdvisedInterceptor.invoke方法,再由DynamicAdvisedInterceptor向下进行传播。