了解 Spring AOP
前必须知道动态代理,这是基础。
原生JDK 动态代理与 CGLIB 动态代理
1. JDK 动态代理
JDK
动态代理是基于接口的,代理的类必须实现某个接口。
public interface UserService {
void addUser();
}
public class UserServiceImpl implements UserService {
public void addUser() {
// 1
System.out.println("addUser 方法执行了");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
UserService target = new UserServiceImpl();
// 生成代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 2
System.out.println("代理方法执行了");
// 3
return method.invoke(target, args);
}
});
// 4
proxy.addUser();
}
}
启动后,执行代理对象的 addUser()
方法,控制台会先输出代理对象的 2
处的语句,然后再输出 1
处的语句。
将断点打在 4
处,可查看生成的代理对象:
$Proxy
:代理对象所属的类。
h
:就是 InvocationHandler
。
target
:被代理对象,InvocationHandler
中的 invoke
方法对原有方法增强后需要执行被代理对象的原始方法,即 3
处。
想查看生成的代理类,需要 main 方法中加入 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true");
便能看到生成的类。
可以看到 $Proxy0
实现了 UserService
接口,所以说 JDK
动态代理是基于接口的,代理对象执行 addUser
的时候,实际执行的是 h
也是就 InvocationHandler
的 invoke
方法。
2. CGLIB 代理
CGLIB
代理是基于类的,会创建被代理对象的子类,所以使用 CGLIB
有几个点需要注意:
被代理的类不能是
final
的,因为final
类型的Class
无法继承。被代理的类必须有默认的或者无参构造方法,因为底层反射创建代理对象的时获取不到构造方法参数。
使用 CGLIB
需要依赖对应 jar
包:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
修改 main
方法:
public static void main(String[] args) {
// 查看 cglib 生成的代理对象
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "cglib");
UserServiceImpl target = new UserServiceImpl();
// 生成代理对象
UserServiceImpl proxy = (UserServiceImpl) Enhancer.create(target.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理方法执行了");
return method.invoke(target, args);
}
});
proxy.addUser();
}
第一行的代码是在当前项目下的 cglib
目录下生成对应的代理类。main
方法执行效果和 JDK
动态代理的效果一样。进入 cglib
目录查看代理类:
可以看到生成的代理对象继承了 UserServiceImpl
,里面的 addUser
方法也和 JDK
动态代理差不多,可自行试验查看。
Spring AOP 中的代理
Spring AOP
生成的代理和原生的 JDK
代理、 CGLIB
稍微有点不一样,先写一个简单的 AspectJ
切面,Spring
版本为 5.3.19
。
@Configuration
@ComponentScan("com.main")
@EnableAspectJAutoProxy // 开启注解 AOP
public class MainConfiguration {
}
@Aspect
@Component
public class UserAspect {
@Before("execution(public * com.main.UserService.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("代理方法执行了");
}
}
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfiguration.class);
UserService bean = context.getBean(UserService.class);
bean.addUser();
}
}
@EnableAspectJAutoProxy
注解中,有一个属性proxyTargetClass
,这个就是控制Spring AOP
使用的是JDK
动态代理还是CGLIB
动态代理,默认值为false
,代表使用JDK
动态代理。但是这并不代表设置为
false
就全部使用JDK
动态代理,因为JDK
动态代理是基于接口的,如果一个类没有实现接口,那就无法使用JDK
动态代理,需要使用CGLIB
代理,这点需要注意。
1. JDK动态代理
同样在 main
方法第一行加入 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true");
查看生成类。
可以看相比于原生的 JDK
动态代理,Spring AOP
生成的代理类多实现了 SpringProxy
、Advised
、DecoratingProxy
三个接口,对着三个接口有印象就行,后续源码中会涉及到。
2. CGLIB 代理
在 MainConfiguration
手动将 @EnableAspectJAutoProxy
注解的 proxyTargetClass
属性设置为 true
,这样所有的代理类都是使用 CGLIB
代理生成。同样在 main
方法第一行加上 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "cglib");
。
相比原生的 CGLIB
代理,Spring AOP
生成的代理类多实现了 SpringProxy
和 Advised
接口。
注意:这里的
Factory
接口是org.springframework.cglib.proxy
包下的,而原生的CGLIB
代理类Factory
接口是net.sf.cglib.proxy
包下的。
Sping AOP 源码分析
1. @EnableAspectJAutoProxy 注解
点进 @EnableAspectAutoProxy
注解
可以看到内部 Import
了一个类:AspectJAutoProxyRegistrar
,而这个类实现了 ImportBeanDefinitionRegistrar
接口,如果熟悉 Spring IOC
的话,那应该对这个接口很熟悉,如果不知道的话,建议先去看看 Spring IOC
的原理,因为后面的讲解是基于 IOC
来的。
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) {
// 1. 注册后置处理器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 2. 解析 @EnableAspectJAutoProxy 的属性并配置
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
由于实现了 ImportBeanDefinitionRegistrar
接口,IOC
注册 beanDefinition
的时候会执行 registerBeanDefinitions()
方法,具体源码在 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions()
,不记得的可以再回顾一下。
第一行就是注册后置处理器,即代理类的创建类,而方法里面明确了要注册的 bean
的类型是 AnnotationAwareAspectJAutoProxyCreator
:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 指定类型:AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
然后,根据类型构造 beanDefinition
,并注册进 BeanDefinitionRegistry
。
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;
}
这个注意一下 bean 的名称是变量
AUTO_PROXY_CREATOR_BEAN_NAME
,实际值为org.springframework.aop.config.internalAutoProxyCreator
2. AnnotationAwareAspectJAutoProxyCreator
通过 IDEA
查看类关系结构:
它实现了几个重要的接口:
BeanPostProcessor
:在postProcessAfterInitialization
方法中创建代理对象。InstantiationAwareBeanPostProcessor
:拦截bean
的创建。AopInfrastructureBean
:实现了该接口的bean
不会被代理。
并继承自核心类 AbstractAutoProxyCreator
。
3. 初始化 AnnotationAwareAspectJAutoProxyCreator
第一步已将对应的 BeanDefinition
注册到 BeanDefinitionRegistry
中了,接下来就要初始化对应的 Bean
了。而 Spring
中初始化 BeanPostProcessor
即后置处理器的地方在 AbstractApplication
中:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
......
try {
this.postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
this.invokeBeanFactoryPostProcessors(beanFactory);
// 这里注册 BeanPostProcessor
this.registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
........
}
}
更深入的源码可以去看 IOC
那部分的文章(TODO),这里不再重复。
4. 作用时机
上一步 registerBeanPostProcessors
方法中已将把 AnnotationAwareAspectJAutoProxyCreator
初始化好了,那接下来的 bean
的创建就会被它所干预。
bean
的创建流程在 IOC
处详细说过,依次是 getBean
、doGetBean
、createBean
、doCreateBean
。在 doCreateBean
中会真正的创建对象、属性赋值、依赖注入和初始化流程。
它对 bean
进行前置或后置处理的的主要就两个方法:postProcessBeforeInstantiation
和 postProcessAfterInitialization
。前一个是 bean
的实例化之前拦截,后一个是 bean
初始化后拦截。
你可能会问其他的
postXXX
方法为什么没有解释一下呢,这是因为AnnotationAwareAspectJAutoProxyCreator
只改造了postProcessBeforeInstantiation
方法和postProcessAfterInitialization
,其他的postXXX
方法用是默认的。
5. AnnotationAwareAspectJAutoProxyCreator # postProcessBeforeInstantiation
前面说过 AnnotationAwareAspectJAutoProxyCreator
实现了 InstantiationAwareBeanPostProcessor
接口,会拦截 bean
的实例化,具体代码在 AbstractAutowireCapableBeanFactory
的 createBean
方法。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
........
Object beanInstance;
try {
// 此处拦截
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
........
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
// 获取所有的 InstantiationAwareBeanPostProcessor,遍历执行 postProcessBeforeInstantiation,只要有一个不返回 null,跳出遍历直接返回
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
AnnotationAwareAspectJAutoProxyCreator
的 postProcessBeforeInstantiation
方法在它的父类 AbstractAutoProxyCreator
中。
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
// 决定是否要提前增强当前 bean
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 被增强过的 bean 不会再次增强
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 基础类型的bean不会被提前增强、被跳过的bean不会被提前增强
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 原型bean的额外处理:TargetSource
// 此处的设计与自定义TargetSource相关,单实例bean必定返回null
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;
}
5.1 InfrastructureClass
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;
}
可以看到 InfrastructureClass
指的是切面、切入点、增强器等等的对象,这些是参与 AOP
代理的,不应该被 AOP
代理。
5.2 shouldSkip
//注意这个方法是在 AspectJAwareAdvisorAutoProxyCreator 中的
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 获取增强器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
// 判断当前bean的名称是否与增强器的名称一致,则认为跳过
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
// 这里才是 AbstractAutoProxyCreator 中的
return super.shouldSkip(beanClass, beanName);
}
// AbstractAutoProxyCreator
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// 检查beanName代表的是不是原始对象(以.ORIGINAL结尾)
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
5.3 findCandidateAdvisors
获取候选的增强器,底层就是解析切面类,构造 Advisor
增强器的过程。
增强器 Advisor
,在 AspectJ
中,对应切面注解 @Before
等和注解标注的方法就可以看做是一个 Advisor
。
// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
进入父类 AbstractAdvisorAutoProxyCreator
:
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
5.3.1 findAdvisorBeans 查找实现了 Advisor 接口的 bean
advisorRetrievalHelper.findAdvisorBeans()
这段源码拆开来看:
public List<Advisor> findAdvisorBeans() {
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// 这里没有初始化对应的 bean
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
}
上面代码就是将 Advisor
的实现类找出来,如果没有,直接返回,不执行下面的逻辑。
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
// logger ......
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
} // catch ......
}
}
}
return advisors;
}
只关注重点 beanFactory.getBean
,这个应该很熟悉了,包含了 bean
的初始化,通过 debug
可以发现,没有候选的增强器。
5.3.2 aspectJAdvisorsBuilder.buildAspectJAdvisors
就是将 AspectJ
切面类,转成增强器。
5.3.2.1 逐个解析IOC容器中所有的bean类型
// BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
Class<?> beanType = this.beanFactory.getType(beanName, false);
这里将容器中所有的 bean
都取出来(父类型为 Object
),在不初始化对应 bean
的前提下,拿到 beanName
对应的 bean
的 class
。
5.3.2.2 解析 Aspect 切面类,构造增强器
......
if (this.advisorFactory.isAspect(beanType)) {
// 当前的 bean 是一个切面类
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
// 单实例 bean
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> 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));
}
}
// AbstractAspectJAdvisorFactory
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
advisorFactory.getAdvisors
,构造增强器:
// ReflectiveAspectJAdvisorFactory
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// 切面类对应的 class
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
// 再次校验类上是否有 @Aspect 注解
validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
// 解析通知方法,封装为 advisor
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS
.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
if (methods.size() > 1) {
methods.sort(adviceMethodComparator);
}
return methods;
}
上面这个方法就是把切面类中没有标注 @Pointcut
注解的方法取出来,并根据相关规则排序。
改造一下之前的 UserAspect
,然后在 getAdvisorMethods
处打断点查看取出的方法:
@Aspect
@Component
public class UserAspect {
@Before("execution(public * com.main.UserService.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("代理方法执行前");
}
@After("execution(public * com.main.UserService.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println("代理方法执行后");
}
public void noAdvice() {
System.out.println("非通知方法");
}
}
可以看到将 UserAspect
中所有的方法取出来了,即便方法上没有 @Before
等通知注解。既然方法上没有通知注解,为什么还取出来呢,别急,下面的方法其实会再做一次过滤。
// ReflectiveAspectJAdvisorFactory
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 增强器的创建
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// 检查方法上面的通知注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// 根据注解的类型, 构造切入点表达式
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
// AbstractAspectJAdvisorFactory
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
ASPECTJ_ANNOTATION_CLASSES
包含了所有通知注解,没有注解的方法会被过滤。如果有,则将切入点表达式的内容,以及参数等信息,封装到 AspectJExpressionPointcut
中。
再打断点,最终可以发现没有标注通知注解的方法已经被过滤掉了:
另外对于多实例 bean
的处理,核心依旧是 advisorFactory.getAdvisors
,只是没有用到 advisorsCache
这个缓存区,这也说明多实例 bean
的解析是多次执行的。
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));
}
5.3.2.3 增强器的创建
getAdvisor
最后会创建一个增强器对象并返回。
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
可以看构造方法中的参数:
expressionPointcut
:AspectJ 切入点表达式的封装。candidateAdviceMethod
:标有通知注解的方法。this
:当前的ReflectiveAspectJAdvisorFactory
。aspectInstanceFactory
:前面代码中的MetadataAwareAspectInstanceFactory
对象。
可以看到增强器本身的结构就是一个切入点表达式 + 一个通知方法,和之前说的完全一致。
5.3.2.4 增强器汇总
buildAspectJAdvisors()
方法最后几行:
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;
增强器汇总完毕,并且将这些数据都放到缓存里面了,接下来就是和 bean
的匹配了。
6. AnnotationAwareAspectJAutoProxyCreator # postProcessAfterInitialization
阅读过 IOC
的应该知道,最终 bean 的初始化会被 BeanPostProcessor
的 postProcessAfterInitialization
处理,进入到 AnnotationAwareAspectJAutoProxyCreator
的 postProcessAfterInitialization
方法中,这个方法其实在父类 AbstractAutoProxyCreator
中,最后会调用 wrapIfNecessary
方法。
// AbstractAutoProxyCreator
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;
}
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;
}
6.1 wrapIfNecessary
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;
}
......
}
先看前面一部分,这块代码和前面的 postProcessBeforeInstantiation
很像,这里不再赘述。
6.2 getAdvicesAndAdvisorsForBean
这个方法很明显就是根据当前正在初始化的 bean
去匹配增强器。
// AbstractAdvisorAutoProxyCreator
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 核心处理
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
// DO_NOT_PROXY 这个静态变量就是 null
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
6.2.1 findCandidateAdvisors
这个方法在 5.3
章节的分析过了,忘记了的话可以跳回去看。
// AnnotationAwareAspectJAutoProxyCreator
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 找 Spring 的原生的增强器
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 找 AspectJ 封装的增强器
// buildAspectJAdvisors 方法 5.3.2 章节中已经分析过了, 这里可以直接从缓存中拿数据
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
6.2.2 findAdvisorsThatCanApply
获取到所有的增强器之后,进行匹配。
// AbstractAdvisorAutoProxyCreator
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 交给 AopUtils
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
// AopUtils
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> 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;
}
findAdvisorsThatCanApply
整体逻辑分为两个部分,前面是针对引介通知的增强器作筛选,后面是普通的方法通知封装的增强器。
对于引介增强器的匹配就不研究了,用得少,感兴趣的可以自行研究。主要还是看普通的增强器。
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;
}
}
对不同的增强器会有不同的处理逻辑,主要看切入点增强器的处理:
// AopUtils
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 连类都切入不进去,那干脆没必要往下走了
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
// 将类实现的接口也加入进来
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
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;
}
}
}
return false;
}
怎么匹配的后面再分析。
回到 findEligibleAdvisors
方法,打断点查看 userService
匹配到的增强器。
6.2.3 extendAdvisors
根据名字理解这个方法扩展了增强器,在这个方法后面打断点,发现还真的多了一个增强器。
// AspectJAwareAdvisorAutoProxyCreator
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
// AspectJProxyUtils
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
// 如果有 AspectJ 包装的增强器且当前的 advisors 里面没有ExposeInvocationInterceptor // 就在 advisors 最前面加一个 ExposeInvocationInterceptor.ADVISOR
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
ExposeInvocationInterceptor.ADVISOR
是什么呢?点进去:
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@Override
public String toString() {
// 这里重写的 toString 方法
return ExposeInvocationInterceptor.class.getName() +".ADVISOR";
}
};
public DefaultPointcutAdvisor(Advice advice) {
this(Pointcut.TRUE, advice);
}
那已经很清楚了,就是一个增强器,类型是 DefaultPointcutAdvisor
,增强器的通知(Advice
)是 ExposeInvocationInterceptor
。
那这个 ExposeInvocationInterceptor
有什么用呢?
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
.....
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
...
}
上面说了这个类是一个 Advice
,可以看到实现了 MethodInterceptor
接口,可以拦截 bean
方法的执行。它的 invoke
方法在当前线程的 ThreadLocal
中放入了当前正在执行的代理对象的方法执行包装。并且这个增强器总是在增强器链中第一个执行,所以上面代码含义就是让后面的增强器都拿到当前正在执行的 MethodInvocation
。
6.3 createProxy 创建代理对象
回到 wrapIfNecessary
方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// getAdvicesAndAdvisorsForBean 找不到匹配的增强器会返回 DO_NOT_PROXY(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;
}
}
匹配到了 bean
对应的增强器后,接下来就是创建代理对象了。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 记录被代理 bean 的原始类型
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 初始化代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 这里即 @EnableAspectJAutoProxy 注解中 proxyTargetClass 的值
if (proxyFactory.isProxyTargetClass()) {
// cglib 代理
if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// JDK 动态代理
if (shouldProxyTargetClass(beanClass, beanName)) {
// 设置 cglib 代理
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);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
6.3.1 shouldProxyTargetClass
先分析下 shouldProxyTargetClass
方法,在 proxyTargetClass
为 false
的情况下:
protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
}
// AutoProxyUtils
public static boolean shouldProxyTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
}
return false;
}
可以看到主要是判断被代理的 bean
的 beanDefinition
中对应属性为 PRESERVE_TARGET_CLASS_ATTRIBUTE
的值是否为 true
。既然这里是 getAttribute
,那肯定有地方 setAttribute
。将源码下下来,CTRL
+ 鼠标左键找到 setAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE,值)
的地方。可以发现是在 ConfigurationClassPostProcessor
这个类 enhanceConfigurationClasses
方法中 set
的,看过前面 IOC
的文章的小伙伴应该有印象吧,这个类可是很重要的。
而 enhanceConfigurationClasses
是哪里被调用的?还是在这个类里面:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
.........
// 这里调用
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
可以看到是在 postProcessBeanFactory
方法中调用的,postProcessBeanFactory
又是 IOC
部分讲过的,所以说看 AOP
之前要先熟悉一下 IOC
哦,不然看到一半就懵了。
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
.......
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
........
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
.........
// 往 configBeanDefs 里 put 数据
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty() || NativeDetector.inNativeImage()) {
// nothing to enhance -> return immediately
enhanceConfigClasses.end();
return;
}
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class
// 这里 set 了属性名 PRESERVE_TARGET_CLASS_ATTRIBUTE 的值为 true
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
..........
}
省略了部分代码,最后一行对 beanDefinition
的 PRESERVE_TARGET_CLASS_ATTRIBUTE
属性赋值了,但是前提是只有在 configBeanDefs
中的 beanDefinition
才会被赋值。那 configBeanDefs
什么时候才不为空呢?往上找往 configBeanDefs
中 put
数据的代码,发现只有 beanDefinition
中属性为 ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE
对应的值为 ConfigurationClassUtils.CONFIGURATION_CLASS_FULL
时这个 beanDefinition
才会加入到 configBeanDefs
中。
还是老方法,CTRL
+ 鼠标左键找到 ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE
被 setAttribute
中的地方,发现在 ConfigurationClassUtils
类 checkConfigurationClassCandidate
方法(看到 ConfigurationClassUtils
是不是很熟悉,还是 IOC
那部分讲过的),继续往上找调用此方法的地方,最终还是回到了类 ConfigurationClassPostProcessor
,在 processConfigBeanDefinitions
方法中,继续往上找,postProcessBeanDefinitionRegistry
方法,这个方法又是 IOC
那部分讲过的。
// ConfigurationClassUtils
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
......
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
// 获取 @Configuration 注解上 proxyBeanMethods 属性的值
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
// 如果 proxyBeanMethods 为 true,则设置为 Full 模式
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
// Lite 模式
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
......
}
proxyBeanMethods
属性有两个选项:true
(默认值)和false
。当设置为true
时,Spring
容器会创建一个CGLIB
代理来封装该配置类,这意味着通过配置类中的@Bean
方法获取的bean
实例,无论调用多少次,都是同一个实例(单例)。这种模式被称为“Full
”模式。相反,当
proxyBeanMethods
设置为false
时,Spring
容器不会创建代理,每次通过@Bean
方法获取的bean
实例都是新的实例(多例)。这种模式被称为“Lite
”模式,它可以提高Spring
应用程序的启动速度和性能,因为它避免了代理的创建和相关的检查。
整个调用链就清晰了 ConfigurationClassPostProcessor # postProcessBeanDefinitionRegistry
-> ConfigurationClassPostProcessor # processConfigBeanDefinitions
-> ConfigurationClassUtils.checkConfigurationClassCandidate
。
public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
......
// 被 @Configuration 注解标注的类,即注解配置类才会设置属性
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
......
}
分析到这就很清楚了,只有被 @Configuration
标注的类才会设置 CONFIGURATION_CLASS_ATTRIBUTE
为 true
,所以 AopUtils # shouldProxyTargetClass
针对的是需要被代理注解配置类。可以做个小实验,修改一下 MainConfiguration
和 UserAspect
的 after
方法,让 UserAspect
可以拦截到 MainConfiguration
,并在 createProxy
处打断点查看结果:
@Configuration
@ComponentScan("com.main")
@EnableAspectJAutoProxy(proxyTargetClass = false)
public class MainConfiguration {
public void test() {
System.out.println("test");
}
}
@Aspect
@Component
public class UserAspect {
@Before("execution(public * com.main.UserServiceImpl.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("代理方法执行前");
}
@After("execution(public * com.main.MainConfiguration.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println("代理方法执行后");
}
public void noAdvice() {
System.out.println("非通知方法");
}
}
进到 if
的方法体里面了,说明 shouldProxyTargetClass
是返回的 true
,而 userService
只是普通 bean
,进入到 else
方法体里面了。
6.3.2 evaluateProxyInterfaces
非配置类进到这个方法,在 proxyTargetClass
为 false
的情况下:
// ProxyProcessorSupport
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
// 获取类实现的接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
// 检查实现的接口是否可代理
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
if (hasReasonableProxyInterface) {
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
else {
// 没有实现接口, 将 proxyTargetClass 设置为 true, 表示需要 cglib 代理
proxyFactory.setProxyTargetClass(true);
}
}
6.3.3 buildAdvisors
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 这个地方是适配Spring原生AOP的MethodInterceptor,感兴趣的小伙伴可自行研究
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
if (specificInterceptors.length > 0) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
}
// 组合原生的方法拦截器,共同作为AOP的通知织入
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
.........
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
最下面有一个 dvisorAdapterRegistry.wrap
方法,字面意思是包装,点进去看:
// DefaultAdvisorAdapterRegistry
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
很简单了,就是将可以支持转换 / 包装为 Advisor
类型的对象适配成 Advisor
。适配的类型,内置的只有 MethodInterceptor
和几种原生的 Advice
。
6.3.4 proxyFactory.getProxy
接下来就是真正创建代理对象了:
// ProxyFactory
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
6.3.4.1 createAopProxy
// ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
private void activate() {
this.active = true;
for (AdvisedSupportListener listener : this.listeners) {
listener.activated(this);
}
}
这里有一个监听器通知的动作,而 AdvisedSupportListener
只在 ProxyCreatorSupport
中使用,查看 Spring
也没有对应的实现接口,我们开发的话基本也不使用,所以稍微看一下就行,主要还是看 getAopProxyFactory().createAopProxy(this)
。
// ProxyCreatorSupport
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
可以通过 debug
发现 aopProxyFactory
的类型是 DefaultAopProxyFactory
。
进入到它的 createAopProxy
方法中:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(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动态代理了的代理对象
// 则使用jdk动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用 cglib 代理
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
看到熟悉的 JDK
、CGLIB
动态代理的字眼了,选择哪种方式就是在这里决定的。
6.3.4.2 AopProxy # getProxy
创建完 AopProxy
后,开始创建代理对象,以 JdkDynamicAopProxy
为例:
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// jdk动态代理的API
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
最下面就是 JDK
的 Proxy.newProxyInstance
。
评论区