🍃前言
前面的博客中,博主对代理模式进行了一个简单的讲解,接下来博主将对spring AOP源码进行简单剖析,使我们对Spring AOP了解的更加深刻。
🍀Spring AOP源码剖析
Spring AOP 主要基于两种⽅式实现的:JDK 及 CGLIB 的⽅式
Spring对于AOP的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成⽣成代理对象的逻辑在⽗类 AbstractAutoProxyCreator 中
相关源码与注解如下:
java">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);
/**
* 检查proxyTargetClass属性值,spring默认为false
* proxyTargetClass 检查接⼝是否对类代理, ⽽不是对接⼝代理
* 如果代理对象为类, 设置为true, 使⽤cglib代理
*/
if (!proxyFactory.isProxyTargetClass()) {
//是否有设置cglib代理
if (shouldProxyTargetClass(beanClass, beanName)) {
//设置proxyTargetClass为true,使⽤cglib代理
proxyFactory.setProxyTargetClass(true);
} else {
/**
* 如果beanClass实现了接⼝,且接⼝⾄少有⼀个⾃定义⽅法,则使⽤JDK代理
* 否则CGLIB代理(设置ProxyTargetClass为true )
* 即使我们配置了proxyTargetClass=false, 经过这⾥的⼀些判断还是可能会将其
设为true
*/
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);
}
代理工⼚有⼀个重要的属性:proxyTargetClass,默认值为false.
也可以通过程序设置
proxyTargetClass | ⽬标对象 | 代理⽅式 |
---|---|---|
false | 实现了接⼝ | jdk代理 |
false | 未实现接⼝(只有实现类) | cglib代理 |
true | 实现了接⼝ | cglib代理 |
true | 未实现接⼝(只有实现类) | cglib代理 |
可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 来设置
需要注意的是:
- Spring Boot 2.X开始,默认使⽤CGLIB代理,可以通过配置项
spring.aop.proxy-target-class=false
来进⾏修改,设置默认为jdk代理
SpringBoot设置 @EnableAspectJAutoProxy ⽆效,因为Spring Boot默认使⽤AopAutoConfiguration进⾏装配
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context =
SpringApplication.run(DemoApplication.class, args);
/**
* HouseProxy houseProxy = context.getBean(HouseProxy.class);
* 设置spring.aop.proxy-target-class=true cglib代理, 运⾏成功
* 设置spring.aop.proxy-target-class=false jdk代理, 运⾏失败, 不能代理类
* 因为 HouseProxy 是⼀个类, ⽽不是接⼝, 需要修改为
* HouseSubject houseProxy = (HouseSubject)
context.getBean("realHouseSubject")
*
*/
HouseProxy houseProxy = context.getBean(HouseProxy.class);
//HouseSubject houseProxy = (HouseSubject)
context.getBean("realHouseSubject");//正确运⾏
System.out.println(houseProxy.getClass().toString());
}
}
注意:使⽤context.getBean()需要添加注解,使HouseProxy,RealHouseSubject被Spring管理测试AOP代理,需要把这些类交给AOP管理(⾃定义注解或使用@Aspect)
我们再看以下代理⼯⼚的代码
public class ProxyFactory extends ProxyCreatorSupport {
//...代码省略
//获取代理
public Object getProxy(@Nullable ClassLoader classLoader) {
//分两步 先createAopProxy,后getProxy
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
//...代码省略
}
createAopProxy的实现在DefaultAopProxyFactory中
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
//...代码省略
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws
AopConfigException {
/**
* 根据proxyTargetClass判断
* 如果⽬标类是接⼝, 使⽤JDK动态代理
* 否则使⽤cglib动态代理
*/
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) ||
ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
//...代码省略
}
接下来就是创建代理了
JDK动态代理
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,
Serializable {
//...代码省略
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " +
this.advised.getTargetSource());
}
return Proxy.newProxyInstance(determineClassLoader(classLoader),
this.proxiedInterfaces, this);
}
//...代码省略
}
CGLIB动态代理
class CglibAopProxy implements AopProxy, Serializable {
//...代码省略
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
//...代码省略
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
//...代码省略
}
以上就是对Spring AOP源码的一个简单剖析。
⭕总结
关于《【JavaEE进阶】 Spring AOP源码简单剖析》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下