springAOP源码1
在介绍AOP之前先讲解一下advice和advisor,以及调用链
先从advice介绍
被代理的类
@Component
public class CalculateTest {
public int add(int i, int j) {
System.out.println ("加");
return i + j;
}
public int subtract(int i, int j) {
System.out.println ("减");
return i - j;
}
public int multiply(int i, int j) {
System.out.println ("乘");
return i * j;
}
public int divide(int i, int j) {
System.out.println ("除");
return i / j;
}
}
下面为两个advice 前后过滤器
public class LogAdviceAfter implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
String methodName = method.getName();
System.out.println("执行目标方法【"+methodName+"】的<后置通知>,入参"+ Arrays.asList(args)+"得到的结果"+returnValue);
}
}
public class LogAdviceBefore implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
String methodName = method.getName();
System.out.println("执行目标方法【"+methodName+"】的<前置通知>,入参"+ Arrays.asList(args));
}
}
Interceptor拦截器
public class LogIntreceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println ("MethodInterceptor方法调用前");
Object proceed = invocation.proceed ();
System.out.println ("MethodInterceptor方法调用后");
return proceed;
}
}
配置类
@Configuration
@ComponentScan(basePackages = "springlearn.aspectjtest")
public class ConfigurationAspectJ {
//以类为单位,不能精确到方法,而且多个类需要多个代理
//在ioc,如果要使用代理那么bean的名称为proxyFactoryBean,bean名称为calculateTest是未代理的类
//这里要注意的是CalculateTest不能是cglib代理之后的类,@Configuration是不可以的,可以使用@Component
@Bean
public ProxyFactoryBean proxyFactoryBean(CalculateTest calculateTest ) {
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean ();
//可以指定advice也可以执行interecptor
proxyFactoryBean.setInterceptorNames ("adviceBefore","logIntreceptor");
proxyFactoryBean.setTarget (calculateTest);
return proxyFactoryBean;
}
@Bean
public LogAdviceBefore logAdviceBefore() {
return new LogAdviceBefore ();
}
@Bean
public LogAdviceAfter logAdviceAfter() {
return new LogAdviceAfter ();
}
@Bean
public LogIntreceptor logIntreceptor() {
return new LogIntreceptor ();
}
}
public class Main {
public static void main(String[] args) {
//查找配置类.配置类有扫描类的路径,满足条件的放到容器中
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext (ConfigurationAspectJ.class);
//获取代理类,bean的名称为proxyFactoryBean,其实就是调用了FactoryBean的getObject方法
CalculateTest calculateTestProxy = ( CalculateTest ) configApplicationContext.getBean ("proxyFactoryBean");
int divide = calculateTestProxy.divide (4, 2);
int add = calculateTestProxy.add (4, 2);
configApplicationContext.close ();
}
}
得到的结果
image.png
Advisor包含了advice和Pointcut,拦截方法和拦截方法做什么.
配置类
@Configuration
@ComponentScan(basePackages = "springlearn.aspectjtest")
public class ConfigurationAspectJ {
//通知(advice):通知类,没有切点 举例:LogAdvice实现了MethodBeforeAdvice接口,切面为CalculateTest类的add和divide方法,LogAdvice会在执行add和divide方法前,执行LogAdvice的before方法,LogAdvice就是通知类
//通知者(advisor): 包含了advice和切点,切点为方法名称,注意这里没有规定哪个类,类是在ProxyFactoryBean中定义的
@Bean
public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisorBefore() {
NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor ();
nameMatchMethodPointcutAdvisor.setAdvice (logAdviceBefore ());
nameMatchMethodPointcutAdvisor.setMappedNames ("divide", "add");
return nameMatchMethodPointcutAdvisor;
}
@Bean
public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisorAfter() {
NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor ();
nameMatchMethodPointcutAdvisor.setAdvice (logAdviceAfter ());
nameMatchMethodPointcutAdvisor.setMappedNames ("divide", "add");
return nameMatchMethodPointcutAdvisor;
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator ();
//以通配符的方式模糊匹配,这样就不用每个类写一个代理
beanNameAutoProxyCreator.setBeanNames ("calculateTest*");
//多个过滤器组成调用链
beanNameAutoProxyCreator.setInterceptorNames ("nameMatchMethodPointcutAdvisorBefore", "nameMatchMethodPointcutAdvisorAfter");
return beanNameAutoProxyCreator;
}
@Bean
public LogAdviceBefore logAdviceBefore() {
return new LogAdviceBefore ();
}
@Bean
public LogAdviceAfter logAdviceAfter() {
return new LogAdviceAfter ();
}
@Bean
public LogIntreceptor logIntreceptor() {
return new LogIntreceptor ();
}
}
public class Main {
public static void main(String[] args) {
//查找配置类.配置类有扫描类的路径,满足条件的放到容器中
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext (ConfigurationAspectJ.class);
//bean的名称为calculateTest,类的本身已经被代理了
CalculateTest calculateTest = ( CalculateTest ) configApplicationContext.getBean ("calculateTest");
int divide = calculateTest.divide (4, 2);
int add = calculateTest.add (4, 2);
configApplicationContext.close ();
}
}
image.png
Advisor可以指定代理的方法和拦截器,多个Advisor形成了调用链,
BeanNameAutoProxyCreator通过名称的方式,将类和Advisor绑定在一起,名称可以使用*作为通配符,这样就可以匹配多个类.
上面讲解了advice和advisor,这样有助于理解AOP的源码.
下面分析AOP的源码,Spring在引入组件的是常用的一种是@EnableXXXX,下面就从
@EnableAspectJAutoProxy入手分析源码
@EnableAspectJAutoProxy的import注解
@Import(AspectJAutoProxyRegistrar.class)
AspectJAutoProxyRegistrar接口继承了ImportBeanDefinitionRegistrar
在springioc容器源码的时候分析过,继承ImportBeanDefinitionRegistrar会调用
registerBeanDefinitions方法
那么在AspectJAutoProxyRegistrar的registerBeanDefinitions方法中会调用
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
代码最终将AnnotationAwareAspectJAutoProxyCreator.class注册进beanDefinitionMap中
AnnotationAwareAspectJAutoProxyCreator类继承图
[图片上传失败...(image-4f9378-1632042893525)]
可以看到AnnotationAwareAspectJAutoProxyCreator继承了很多的Bean的后置处理器,
我们分析过bean的后置处理器的9处调用,AOP的advisor包装和创建cglib动态代理都是在bean的后置处理器中完成的
- InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法的调用.
真正执行AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation
其主要的作用是创建Advisor,并缓存起来
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//缓存,不用重复的查找,第一次为空
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.*hasLength*(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; }
// advisedBeans成员变量,如果为false是不需要代理的,比如Advice的子类或者标注了@Aspect的类,本身是服务于代理类的,当然是不需要代理的
// isInfrastructureClass(beanClass)判断beanClass不是Advice,Pointcut,Advisor,AopInfrastructureBean类及子类,
//重点shouldSkip方法,获取beanDefinitionMap中关于AOP的类(Advice的实现类和标注了@Aspect注解的类),我们这里只关注了是标注@Aspect注解的类, shouldSkip下面会分析 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.*FALSE*);
return null; }
} // Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) { if (StringUtils.*hasLength*(beanName)) { this.targetSourcedBeans.add(beanName); }
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy; } return null; }
shouldSkip方法中的findCandidateAdvisors()方法,寻找Advice的实现类和标注了@Aspect的类, findCandidateAdvisors()被重写了,那我们关注重写的方法
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
super. findCandidateAdvisors寻找beanDefinitionMap中所有Advisor的子类
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());查找标注了@AsceptJ注解的类,并把所有找到的类包装为Advisor类,那我们就分析
this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法
public List<Advisor> buildAspectJAdvisors() {
//从缓存中获取标注了@Aspect的类
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
//线程安全,防止多线程加载@Aspect
synchronized (this) {
aspectNames = this.aspectBeanNames;
//单例模式中的双重校验,提高效率
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//从bean定义Map中获取Object的子集,也就是获取所有的bean定义
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
//获取类
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (beanType == null) {
continue;
}
//判断类是否标注了@Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//将类中标注了Pointcut.class, Around.class, Before.class, After.class, //AfterReturning.class, AfterThrowing.class 注解的方法,经过组合,封装成
//InstantiationModelAwarePointcutAdvisorImpl的实例集合
//每个InstantiationModelAwarePointcutAdvisorImpl包含Advice和PointCut
//方法不跟进去了,主要脉络是首先找到除标注@Pointcut注解的方法,再去掉Object自带
//方法(equal,hashCode,notify等),包装为Advisor
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
//将Advisor缓存起来,key为bean的名称,这里是所有类的产出的Advisor缓存起来
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
//将得到的InstantiationModelAwarePointcutAdvisor存放到缓存中
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
shouldSkip方法在判断类是否需要跳过(跳过就是map中的value为false不需要代理的意思)的同时,找到@Aspect和Advice的子类,并存放到缓存中
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && 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;
}
// Create proxy if we have 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;
}
- BeanPostProcessor# postProcessorsAfterInitialization后置处理器
真正执行的是AbstractAutoProxyCreator#postProcessorsAfterInitialization
其主要作用遍历bean定义,与Advisor匹配,如果匹配成功则创建动态代理
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
warpIfNecessary是重要方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && 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;
}
// Create proxy if we have advice.
//如果类中只要有一个方法满足了Advisor,这该类需要代理,下面会分析到
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;
}
调用的是AbstractAdvisorAutoProxyCreator重写的方法
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
继续调用List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
下面为findEligibleAdvisors方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//判断类是否满足AspectJ的切点表达式,主要分两步初步筛选和精确筛选
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//添加了自带的Advisor
extendAdvisors(eligibleAdvisors);
//进行排序,如果beanClass满足了两个AspectJ标注的类,比如都有@Before,那用@Order
//来判断前后,是一种包裹的关系 比如 before1前置 before2 前置 after2后置
//after1后置 1把2包裹起来
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
当beanClass匹配至少一个Advisor就可以创建代理了
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new
SingletonTargetSource(bean));
createProxy创建代理类后续继续分析