DefaultAopProxyFactory
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (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)) {
标记1:return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
标记1处:目前想到的是适配为了用户这样实现动态代理
public static void main(String[] args) {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTargetSource(new TargetSource() {
@Override
public Class<?> getTargetClass() {
return Vehicle.class;
}
@Override
public boolean isStatic() {
return false;
}
@Override
public Object getTarget() throws Exception {
return new CarHasInterface();
}
@Override
public void releaseTarget(Object target) throws Exception {
}
});
advisedSupport.setProxyTargetClass(true);
new DefaultAopProxyFactory().createAopProxy(advisedSupport).getProxy();
}
一、简单来说:
JDK动态代理生成的代理类需要 实现被代理类(真实类)的接口,重写其中的方法
CGLIB动态代理生成的代理类 需要继承被代理类(真实类),覆盖其中的方法
二、Spring在选择用JDK还是CGLiB的依据:
(1)具体使用哪个,首先取决于配置,再取决于bean自身是否实现接口。关键配置( spring.aop.proxy-target-class) ,这个与spring-configuration包版本有关系
spring.aop.proxy-target-class=true :强制全部使用Cglib动态代理织入增强
spring.aop.proxy-target-class=false :自动选择代理方式(若类实现接口,则使用JDK动态代理,若没有实现接口,则使用Cglib动态代理)
org.springframework.boot:spring-boot-configuration 版本是2.x时,此配置默认是true; 版本1.x时: 当使用spring事务管理时,默认是true,其他情况,默认是false
2.x
{
"name": "spring.aop.proxy-target-class",
"type": "java.lang.Boolean",
"description": "Whether subclass-based (CGLIB) proxies are to be created (true), as opposed to standard Java interface-based proxies (false).",
"defaultValue": true
}
1.x
{
"name": "spring.aop.proxy-target-class",
"description": "Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false). Defaults to \"true\" when using Spring Transaction Management, otherwise \"false\".",
"type": "java.lang.Boolean"
}
三、CGlib比JDK快?
(1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
(2)在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。