spring aop是spring框架的一大核心,用过spring的人应该对于这个内容不会感到陌生。但是,肯定会有人对于spring aop和aspectJ以及proxy和CGLIB比较混乱。
动态代理java里面最常用的一般就是jdk的proxy接口代理,以及CGLIB的继承代理,而spring aop是基于这两种代理的一种封装,具体哪种代理可以根据配置选择,而aspectJ是一个第三方的代理框架,本身和spring毫无关系,但是由于可能是spring自觉得aspectJ语法比较人性化,所以spring将aspectJ中的一些语法做法整合到了spring aop中,注意并不是直接把aspectJ给整合进来了。
所以spring中经常说的@Aspectj的支持,不是指的是和aspectJ整合,而是spring aop自身的一套aspectJ语法,而我们为啥使用注解需要导入aspectJ的包,那是因为spring aop实现aspectJ语法用的注解都是aspectJ包里面的。
当然spring也确确实实整合了aspectJ,不过这个怎么用的就是另外一回事了。
好了,正式开始梳理源码,这里就从@Aspectj注解的实现开头。
spring需要支持@AspectJ,需要添加@EnableAspectJAutoProxy注解,现在的spring boot不需要这个注解是因为spring boot通过条件注解来初始化的。EnableAspectJAutoProxy注解是一个import注解,里面内置了一个@import,导入的类是AspectJAutoProxyRegistrar,这个类是一个实现了ImportBeanDefinitionRegistrar接口的import类,所以就得看这个类registerBeanDefinitions注册了什么
看下面两段代码,可以看到,这里会注册一个AnnotationAwareAspectJAutoProxyCreator类的BeanDefinition 返回,所以,这个AnnotationAwareAspectJAutoProxyCreator类很明显是重中之重。
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
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;
}
那么就先看一看AnnotationAwareAspectJAutoProxyCreator的类图,从分析类图开始
AnnotationAwareAspectJAutoProxyCreator类继承图看点有三条,首先最明确的是几个Aware接口,所有的Aware接口都是为了注入一些属性,例如BeanFactoryAware就是为了注入beanFactory。第二点是SmartInstantiationAwareBeanPostProcessor,这个接口继承自InstantiationAwareBeanPostProcessor,再继承自BeanPostProcessor,这三个接口在spring ioc这篇博客中出场率还是很高的,在spring ioc的生命周期中起的作用都非常重要。最后就是中间这条主干,这条主干的类继承基本都是为了实现SmartInstantiationAwareBeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor这三个接口的方法。
因此,再来回顾一下spring ioc关于这三个接口的一些内容。
首先BeanPostProcessor不同于普通的Bean,BeanPostProcessor是在refresh方法的registerBeanPostProcessors中从所有的BeanDefinition中查找出来,注册到BeanFactory中。
再看看执行顺序
1、首先是InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法。
执行时间在Bean创建对象之前。
2、如果postProcessBeforeInstantiation有bean返回,那么会直接调用这个接口的postProcessAfterInitialization方法,否则populateBean中被调用,3步骤之后
执行时间在Bean创建对象之前,紧接着1之后执行。
3、SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法
执行时间在Bean创建对象之前,可以看出在创建对象中。
4、InstantiationAwareBeanPostProcessor的postProcessProperties方法
执行时间在Bean创建对象之后,设置对象属性值的时候。
5、SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法
执行时间设置对象属性值的时候,和循环依赖有关系,在4步骤中
6、InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法
执行时间在Bean创建对象之后,设置对象属性值的时候,紧接着4之后执行
7、BeanPostProcessor的postProcessBeforeInitialization方法
执行时间在Bean执行各种init之前,在各种setAware之后,因为执行顺序,所以基本所有的Aware都调用完后才会被调用
8、BeanPostProcessor的postProcessAfterInitialization方法
执行时间在Bean执行各种init之后。
另外还有一个SmartInstantiationAwareBeanPostProcessor的predictBeanType方法,用于是否匹配类型这一块捋清楚之后,再来一步一步分析代码。
先看1、InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法
在类还没反射生成实例的时候,这里传入了类的类型和bean的名称,做了如下操作
首先或判断当前类是否继承了
Advice、Pointcut、Advisor、AopInfrastructureBean四个接口,
或者是以.ORIGINAL结尾,
最后还调用了子类的方法来判断。
findCandidateAdvisors方法用于找出Bean中所有继承了Advisor接口的类以及@aspect注解的类,并生成Advisor列表 ,Advisor算是切面。
而在这个过程中,这个Bean就会被放入spring容器中了。
@Override
protected List findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
buildAspectJAdvisors方法中获取出spring容器中所有的bean的名称,用bean的名称获取类型,再反射查看是否有@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);
List classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
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));
}
}
有的话进入条件往下执行getAdvisors方法
先获取这个类所有的方法,不包括有@Pointcut注解的方法,依次循环
for (Method method : getAdvisorMethods(aspectClass)) {
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
// to getAdvisor(...) to represent the "current position" in the declared methods list.
// However, since Java 7 the "current position" is not valid since the JDK no longer
// returns declared methods in the order in which they are declared in the source code.
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
// discovered via reflection in order to support reliable advice ordering across JVM launches.
// Specifically, a value of 0 aligns with the default value used in
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
查看方法上是否有以下这几个注解,有的话,获取注解,获取注解上的表达式,生成InstantiationModelAwarePointcutAdvisorImpl
最后判断集合中如果有AspectJPointcutAdvisor继承类,并且名称和bean名称相同的跳过,这里如果是注解@Aspect的明显不会有,肯定不会返回true,但如果存在继承Advisor并返回AspectJPointcutAdvisor的类,所有的类执行shouldSkip就会都返回true。
接下来看看有没有自定义的customTargetSourceCreators,如果有的话,这里就会生成代理返回。在这种情况下,会立即执行postProcessAfterInitialization,AbstractAutoProxyCreator实现方法中什么也没做
@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;
}
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;
}
再看3、4、6、7,实现类也什么都没做。
来看5、SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法,这是当有循环依赖 比如 a、b互相依赖,先创建a的话,那么a最后就会调用到这个方法。
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
这里先放一下。
看8、postProcessAfterInitialization方法,结合5,这里就很明了了,如果有5,在5中会把已经创建的bean放入到earlyProxyReferences缓存map中,并且调用wrapIfNecessary方法,如果5已经执行过,8就不执行了。
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@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;
}
所以重点看wrapIfNecessary方法做了什么,方法中会为当前类找出对应的Advisors并进行代理,这里同样也调用了findCandidateAdvisors方法,这个方面上面已经分析过了,会返回一个Advisor的列表
/**
* Find all eligible Advisors for auto-proxying this class.
* @param beanClass the clazz to find advisors for
* @param beanName the name of the currently proxied bean
* @return the empty List, not {@code null},
* if there are no pointcuts or interceptors
* @see #findCandidateAdvisors
* @see #sortAdvisors
* @see #extendAdvisors
*/
protected List findEligibleAdvisors(Class> beanClass, String beanName) {
List candidateAdvisors = findCandidateAdvisors();
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
拿到Advisor的列表之后,再进行筛选匹配,找出当前类能用的Advisor。
/**
* Search the given candidate Advisors to find all Advisors that
* can apply to the specified bean.
* @param candidateAdvisors the candidate Advisors
* @param beanClass the target's bean class
* @param beanName the target's bean name
* @return the List of applicable Advisors
* @see ProxyCreationContext#getCurrentProxiedBeanName()
*/
protected List findAdvisorsThatCanApply(
List candidateAdvisors, Class> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
往下,循环Advisor列表,先找出是否有继承自IntroductionAdvisor(引入增强),调用canApply判断方法。接着再找其他的,并传入参数hasIntroductions ,参数标识当前类有没有能用的IntroductionAdvisor
/**
* Determine the sublist of the {@code candidateAdvisors} list
* that is applicable to the given class.
* @param candidateAdvisors the Advisors to evaluate
* @param clazz the target class
* @return sublist of Advisors that can apply to an object of the given class
* (may be the incoming List as-is)
*/
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
/**
* Can the given advisor apply at all on the given class?
* This is an important test as it can be used to optimize out a advisor for a class.
* This version also takes into account introductions (for IntroductionAwareMethodMatchers).
* @param advisor the advisor to check
* @param targetClass class we're testing
* @param hasIntroductions whether or not the advisor chain for this bean includes
* any introductions
* @return whether the pointcut can apply on any method
*/
public static boolean canApply(Advisor advisor, Class> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
最后调用切点表达式的match方法,这里有两个match,一个类级别的match,Pointcut继承类都会有getClassFilter和getMethodMatcher两个方法,分别存放了类和方法的匹配类
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
一个方法的match
for (Class> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
经过类和方法的过滤,这里就会找出能够使用的Advisor。
找到匹配的Advisor列表之后返回,调用extendAdvisors方法,这个方法向Advisor列表最前面添加了一个DefaultPointcutAdvisor,这个类包含了一个ThreadLocal用来保存MethodInvocation,主要用于AspectJ的aop代理。
接着继续返回然后调用createProxy创建代理类
/**
* Create an AOP proxy for the given bean.
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(Class> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
到了这里代码就很简单了,通过配置的proxyTargetClass属性,以及存不存在接口决定使用JDK的动态代理还是CGLIB的代理
/**
* Create a new proxy according to the settings in this factory.
* Can be called repeatedly. Effect will vary if we've added
* or removed interfaces. Can add and remove interceptors.
*
Uses the given class loader (if necessary for proxy creation).
* @param classLoader the class loader to create the proxy with
* (or {@code null} for the low-level proxy facility's default)
* @return the proxy object
*/
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
所以说代理的实现都是spring来实现的,AspectJ只是语法上的支持.