(四)AOP切面使用与原理

SpringAOP的使用和源码分析

前言

现在来看(Aspect-oriented Programming) 面向切面编程aop,是和oop(Object-oriented Programming)是对编程结果的不同的思考的方向。在面向对象中,形成组合的组件是类(class)。而在面向切面,形成组合的组件是切面(Aspect),切面能够对关注的地方模块化,横切多种不同的类型和对象(比如事务管理)。而这个所谓的“关注的地方”,也可以在AOP中称为跨领域关注点

Spring提供 配置文件 和 @AspectJ注解 方式编写AOP,两种方式都支持各种的 Advice(通知),如果使用@AspectJ注解,仍然会通过Spring的进行织入。

AOP中关键字的概念

1.Aspect

切面: 对多种不同的类的横切关注点,这个关注点被模块化为一个类,这个类就叫做切面(切面类),通过在普通类上标注 @Aspect注解来实现。

2.Join point

连接点:程序执行过程中能够执行通知(Advice)的点。

3.Advice

通知:通知指的是切面在指定的连接点处执行的操作,不同的通知类型包括:“around”, “before” and “after”

4.Pointcut

切点:切点会匹配通知所要织入的一个或者多个连接点,通知是与切点向关联的,并且在任何匹配到切点的地方执行在连接点上的操作。

5.Target object

目标对象:一个【被一个或多个切面进行通知】的对象叫做目标对象,也叫代理对象。

6.AOP proxy

AOP代理:在Spring中,一个是JDK动态代理,一个是 CGLIB 代理。

7.Weaving

织入:织入是将切面应用到目标对象来创建的代理对象过程

使用注解方式进行AOP的配置和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 1. 使用 @Aspect 注解创建切面类
* 2. 使用 @Pointcut 注解注明切点(使用Aspect表达式)
* 3. 声明通知(Before,After,Around,AfterReturning,AfterThrowing)具体含义可以参考Ref文档 5.4.4. Declaring Advice
* 只是以上三步是不行的,因为没有开启Spring对注解版AOP的支持
* 所以,需要使用 @EnableAspectJAutoProxy 开启对@Aspect注解的支持
**/
@Aspect
@Component
public class LogAspects {

@Pointcut(value="within(com.nanyin.service.*)")
// @Pointcut("execution(public * (..))")
public void pointCut(){
}

@Before("pointCut()")
public void logBefore(JoinPoint jp){
System.out.println(jp.getSignature().getName());
System.out.println("before...");
}

@After("pointCut()")
public void logAfter(){
System.out.println("after...");
}

@AfterReturning("pointCut()")
public void logAfterReturn(){
System.out.println("after return...");
}

@AfterThrowing(value = "pointCut()",throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint,Exception ex){
joinPoint.getSignature().getName();
System.out.println("after throwing...");
System.out.println(ex.getMessage());
}
// around在proceed 之前是在 before之前执行
// around在proceed 之前是在 after之前执行
// 可兼容before和after
@Around("pointCut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 方法开始
System.out.println("around methods begin ...");
Object object = joinPoint.proceed();
System.out.println("around methods end ...");
return object;
}
}

/**
* 进行测试
*
**/
@Test
public void test1(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BasicConfig.class);
BasicService basicService = (BasicService) applicationContext.getBean("basicService");
// 因为切点包括这个basicService,所以执行hello就会触发AOP
basicService.hello();
}

// 结果
around methods begin ...
hello
before...
hello world!!
around methods end ...
after...
after return...

AOP代码原理分析

通过以上实践,可以看到如果需要使用Spring的AOP功能,需要先使用 @EnableAspectJAutoProxy 注解标注在配置类中,使 @Aspect 生效为一个切面类。

1. @EnableAspectJAutoProxy 开启springAOP支持

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Target(ElementType.TYPE) //标注在类上
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) //引入 AspectJAutoProxyRegistrar
public @interface EnableAspectJAutoProxy {
/**
* 是否使用CGLIB进行代理,默认是false,即默认使用JDK动态代理
**/
boolean proxyTargetClass() default false;
/**
* 是否需要 代理应由AOP框架公开为{ThreadLocal},以便通过{AopContext}类进行检索。
**/
boolean exposeProxy() default false;
}

可以看到这里使用了Import注解,将AspectJAutoProxyRegistrar 引入到配置中。引入后,会通过继承自ImportBeanDefinitionRegistrar接口的方法 registerBeanDefinitions 做后续处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//如果需要 注册AspectJ注解自动代理创建类 internalAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// ...
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 注册或升级AutoProxyCreator AnnotationAwareAspectJAutoProxyCreator 这个类是用来处理所有的AspectJ注解的切面
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

最后通过 registerOrEscalateApcAsRequired 方法将 cls 也就是 AnnotationAwareAspectJAutoProxyCreator 注册到容器中,名称为 internalAutoProxyCreator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
// cls=AnnotationAwareAspectJAutoProxyCreator
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 是否存在internalAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// ...
}
// 获得一个 AnnotationAwareAspectJAutoProxyCreator 的 beanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册名为 org.springframework.aop.config.internalAutoProxyCreator 的类
// 实际对应的是 AnnotationAwareAspectJAutoProxyCreator 类,而这个类是用来使@Aspect起作用的
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}

经过上面的分析能够了解通过使用 @EnableAspectJAutoProxy 这个注解,能够将AnnotationAwareAspectJAutoProxyCreator引入到容器中,从而达到解析,使用AOP。

那么 AnnotationAwareAspectJAutoProxyCreator 是如何工作的呢?为何引入这个类,才能使用Spring的AOP功能呢?

2. @AnnotationAwareAspectJAutoProxyCreator

类结构初步分析

图1

AnnotationAwareAspectJAutoProxyCreator 生成类结构图,可以看到它继承自有两个顶级接口,分别是 BeanPostProcesserAware 接口。

  • Aware 接口主要用于标记超级接口,用于指示bean有资格通过回调样式方法由Spring容器通知特定框架对象。

  • BeanPostProcesser 可以通过实现 BeanPostProcesser的两个后置处理器来实现对Bean的前后置处理:1.postProcessBeforeInitialization(Object bean, String beanName) 2.postProcessAfterInitialization(Object bean, String beanName) 分别针对初始化前后的拦截处理。

a. AbstractAutoProxyCreator

在通过上面图片中所看到的 AbstractAutoProxyCreator 继承了 ProxyProcessorSupport

继承类/接口 作用 需要实现方法
ProxyConfig类 用于创建代理的配置的便利超类,保证所有的代理创建类有一致的属性
Ordered接口 表示继承类是有序的
BeanClassLoaderAware接口 使用指定的classLoader来加载Bean setBeanClassLoader(ClassLoader classLoader)
AopInfrastructureBean接口 标示该Bean是作为Spring AOP的基础组件进行使用,因此不会被代理,即使被PointCut指定到也不会被代理到
BeanFactoryAware 使用指定的 BeanFactory 来实例化Bean void setBeanFactory(BeanFactory beanFactory)
b. SmartInstantiationAwareBeanPostProcessor

AbstractAutoProxyCreator -> 实现自 SmartInstantiationAwareBeanPostProcessor -> 继承自 InstantiationAwareBeanPostProcessor -> 继承自 BeanPostProcessor.

  • InstantiationAwareBeanPostProcessor

在这个接口中,不仅仅有继承于 BeanPostProcessorpostProcessBeforeInitialization(Object bean, String beanName)postProcessAfterInitialization(Object bean, String beanName) 两个Bean初始化前后的处理方法,本身还定义了 postProcessPropertiespostProcessPropertyValues方法。作用是在针对Bean的初始化后对属性进行后置处理。

  • SmartInstantiationAwareBeanPostProcessor

在这个接口中定义两个方法,分别为 default Class<?> predictBeanType(Class<?> beanClass, String beanName) 用来预测使用BeanPostProcessor的postProcessBeforeInstantiation方法的返回类型,默认为null。default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) 用来决定使用哪个候选的构造器。

此时,相比已经在前面了解到什么是AOP,同时可以在前面的类结构分析中得知了AnnotationAwareAspectJAutoProxyCreator 继承自InstantiationAwareBeanPostProcessor 从而实现了对Bean的前后处理。所以下面来着重找和 对Bean 前后置处理相关的方法。

AbstractAutoProxyCreator类源码分析

AbstractAutoProxyCreator 作为 AnnotationAwareAspectJAutoProxyCreator 的父类,起到了非常重要的作用。

AbstractAutoProxyCreator 中,实现了 BeanPostProcessor 的初始化前后处理方法,用来针对每次初始化Bean前后对切面的识别判断和对符合条件的Bean进行通知的代理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// postProcessBeforeInitialization ,BeanPostProcessor的实现方法。
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName); //获得beanClass

if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
// 通过判断是否使用了@AspectJ注解定义的切面类还是
// 实现Advice、Pointcut、Advisor、AopInfrastructureBean
this.advisedBeans.put(cacheKey, Boolean.FALSE); //添加到advisedBeans里面,等待处理
return null;
}
}
//如果不是基础设施的类
TargetSource targetSource = getCustomTargetSource(beanClass, beanName); //获得targetSource
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;
}

postProcessBeforeInstantiation实现类中,具体流程大致为

  • 如果是Aspect切面类,则将类添加到advisedBeans中等待进行Advice的组装
  • 如果不是切面类,则会先去判断是否自定义一个 customTargetSourceCreators 数组
    • 如果定义了,则组装成自定义的代理类进行返回。
1.是否为AspectJ配置类

如果是AspectJ定义的切面类,或者由Advice、Pointcut、Advisor、AopInfrastructureBean实现类,则添加到advisedBeans中,并制定值为FLASE。

AnnotationAwareAspectJAutoProxyCreator 中存在 的isInfrastructureClass 实现方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Override
protected boolean isInfrastructureClass(Class<?> beanClass) {
// 加上父类中的isInfrastructureClass判断规则
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
// 在这里判断是否存在 Aspect 注解
private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
// AbstractAutoProxyCreator 中的方法
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) || //是否实现 Advice
Pointcut.class.isAssignableFrom(beanClass) || //是否实现 Pointcut
Advisor.class.isAssignableFrom(beanClass) || //是否实现 Advisor
AopInfrastructureBean.class.isAssignableFrom(beanClass); //是否实现 AopInfrastructureBean
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
2.进行代理

真正的代理是发生在实现的 beanPostProcessorpostProcessAfterInitialization

AbstractAutoProxyCreator 中提供类一个初始化后置处理器 postProcessAfterInitialization

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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;
}
//如有必要,包装给定的bean,即是否有资格被代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
// 如果在 postProcessBeforeInitialization 中定义了targetSourcedBeans,则直接返回
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
// 如果已经添加到advisedBeans中也直接返回
return bean;
}
// 如果是一个基本配置Aspect类,则放到advisedBeans中。
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// 创建Advice
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// Advice存在,则表示需要代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
// 返回代理对象。
return proxy;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

创建Advice的Bean增强过程如下:

  1. 每个Bean在执行invokeInitMethods进行Init,然后进入到Init后置处理器中
  2. 通过在 AbstractAutoProxyCreatorpostProcessAfterInitialization 对代理类的包装
    1. 通过getAdvicesAndAdvisorsForBean获取所有的可用的advice增强器。
    2. 通过 createProxy 创建代理Bean,并返回代理对象。
3.Advice获取过程

​ Advice是进行代理的重要的组成部分,代码中可以通过 @AspectJ 注解在切面类上, 同时使用Advice相关注解如 @After @Before 等进行标注,声明为一个 Advice

​ 实际源码分析时会发现不管是 postProcessBeforeInstantiation 还是 postProcessAfterInstantiation,最后都会通过 buildAspectJAdvisors 方法寻找所有的候选的 advice。其中有两个比较重要的地方需要注意:

  • 为了避免重复,使用了对aspectBeanNames的判断,如果判断为空,才会进行Advice的查找
1
2
3
4
5
6
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
// ....
  • 通过getAdvices获取所有的备选的Advice
1
2
3
4
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);// 获取Aspect类中的Advice
if (this.beanFactory.isSingleton(beanName)) {// 如果是单例的
this.advisorsCache.put(beanName, classAdvisors);// advisorsCache 是以 BeanName为Key,List<Advice>为value的Map
}
  • 通过getAdvices中的getAdvisorMethods获取排除除去Pointcut 标注的所有方法。
1
2
3
4
5
6
7
8
9
10
11
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { // 除去标注了Pointcut注解的方法 添加到 "method"中
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
methods.sort(METHOD_COMPARATOR);
return methods;
}
  • 最后通过getAdvices中的getAdvisor中的getPointcut方法,通过 findAspectJAnnotationOnMethod对类中不存在 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class进行过滤。
1
2
3
4
5
6
7
8
9
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;
}
  • 最后在buildAspectJAdvisors方法中放入到advisorsCache,作为缓存。
1
2
3
4
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);// 获取Aspect类中的Advice
if (this.beanFactory.isSingleton(beanName)) {// 如果是单例的
this.advisorsCache.put(beanName, classAdvisors);// advisorsCache 是以 BeanName为Key,List<Advice>为value的Map
}
4.方法的匹配

在进行代理的时候,如何知道对那些方法进行了代理。

  • 在后置处理器使用的时候,通过getAdvicesAndAdvisorsForBean获取缓存中的Advice
1
2
3
4
5
6
7
8
9
// 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;
}
  • 通过其中的 findEligibleAdvisors方法,获取可用的Advice
  • 一步一步点进去后,发现最后使用canApply方法进行判断,是否可以对当前Bean进行代理
1
2
3
4
5
6
7
8
9
10
11
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;
}
// 使用Matcher进行类级别的匹配验证
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}

综上解析中,能够解决一下几个疑问:

  1. AnnotationAwareAspectJAutoProxyCreator 作用是什么

    最重要的是引入了AbstractAutoProxyCreator,实现对Bean的代理包装;同时在postProcessBeforeInstantiation时,在使用 shouldSkip 时,会获取所有的Advice,并加入到cache中。

  2. Spring在什么时候进行AOP代理?
    Spring在生成Bean单例时会执行Init方法初始化,通过初始化后postProcessor方法,先获取所有可用的Advice增强器,之后使用ProxyFactory创建Proxy并返回。

  3. 容器获取Advice的过程?

    在前置处理器中,获取@AspectJ中下的所有Advice方法,并添加到缓存中

  4. 哪些方法可以被匹配到可以进行AOP?
    在PointCut中执行范围中的Bean可以被AOP拦截使用

3. 创建代理的方式

SpringAOP创建代理有两种方式:

  • 第一种:使用JDK动态代理
  • 第二种:使用CGLIB代理。

下面来针对代理方式的选择方式,查看源码一探究竟。

在上一节中提到的在 AbstractAutoProxyCreator 中的在后置处理器中 postProcessAfterInitializationwrapIfNecessary中进行了对Bean的代理包装处理.

1
2
3
4
5
6
7
8
9
10
// 如果存在可用的通知,则对Bean进行代理
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;
}

createProxy 中决定了使用哪种方式(JDK动态代理、CGLIB代理)进行代理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

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)) {
// 如果 proxy-target-class 标签属性返回true,则表明需要基于类的代理,
// 反之则需要基于接口的代理
proxyFactory.setProxyTargetClass(true); //使用CGLIB代理(true)
}else {
evaluateProxyInterfaces(beanClass, proxyFactory); //检查是否实现了接口
// 如果实现了接口,则设置interface,否则设置proxyTargetClass为true,但前提是
// 用户没有自己设置proxyTargetClass属性
/**
* if (hasReasonableProxyInterface) {
* Must allow for introductions; can't just set interfaces to the target's interfaces only.
* for (Class<?> ifc : targetInterfaces) {
* proxyFactory.addInterface(ifc);
* }
*}else {
* proxyFactory.setProxyTargetClass(true);
*}
*/
}
}
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());
}

在这里设置了有关于proxyFactory的相关属性, 如是否继承接口的interface,和 ProxyTargetClass 。如果没有实现interface,则会自动将ProxyTargeClass为true,也就是说这两个属性是相对的。

在最后的retrun的 getProxy() 方法最终会调用 DefaultAopProxyFactory 类中的 createAopProxy 方法决定使用哪中代理方式进行代理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
/*
* 下面的三个条件简单分析一下:
*
* 条件1:config.isOptimize() - 是否需要优化
* 条件2:config.isProxyTargetClass() - 检测 proxyTargetClass 的值,
* 条件3:hasNoUserSuppliedProxyInterfaces(config) - 目标 bean 是否实现了接口
*
*/
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 如果设置了optimize 或者 proxyTargetClass 或者设置了进行代理的接口
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config); //如果代理的是接口,使用JDK动态代理
}
return new ObjenesisCglibAopProxy(config);//否则使用CGlib代理
}
else { //否则都使用JDK进行代理
return new JdkDynamicAopProxy(config);
}
}

前面说的如果自己设置类proxyTargetClass属性为true,就不会判断是继承了interface。如果没有单独设置,则会先判断是否继承了接口,如果没有则会自动设置proxyTargetClass属性为true。

所以得出结论:

  1. 如果设置了proxyTargetClass为true,则使用CGLIB代理
  2. 如果没有设置proxyTargetClass,如果是接口,则使用JDK动态代理。如果没有实现接口,则还是会使用CGLIB进行代理。
-------------本文结束感谢您的阅读-------------