0%

cglib动态代理


首先我们看一下如何实现cglib的动态代理


cglib通过实现MethodInterceptor接口来实现动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class DemoMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before in cglib");
Object result = null;
try{
result = methodProxy.invokeSuper(o, objects);
}catch (Exception e){
e.printStackTrace();
throw e;
}finally {
System.out.println("after in cglib");
}
return result;
}
}


下面代码是告诉我们如何实现cglib的调用

1
2
3
4
5
6
7
8
9
public class MethodInterceptorClient {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new DemoMethodInterceptor());
Subject subject = (Subject) enhancer.create();
subject.hello();
}
}



JDK与Cglib代理对比

JDK只能针对有接口的类的接口方法进行动态代理
Cglib基 于继承来实现代理,无法对static、final类进行代理,
Cglib基于继承来实现代理,无法对private、static方法进行代理

最后我们看看Spring还如何创建动态代理类的

这里写图片描述

下面我们看一下DefalutAopProxyFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
public DefaultAopProxyFactory() {
}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}

private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
}
}

在代码中我们可以看到有!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)这三个选项,如果这三个都不满足就会走JDK的实现。或者本身是JDK代理的话也会走JDK代理,其他都是走cglib代理


那我们如何强制使用cglib呢

1
2
3
4
5
6
7
8
@SpringBootApplication
// 强制使用cglib
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AopDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AopDemoApplication.class, args);
}
}


总结:
如果目标对象实现了接口,则默认采用JDK动态代理
如果目标对象没有实现接口,则采用Cglib进行动态代理
如果目标对象实现了接口,且强制cglib代理,则使用cglib代理