1.概述
上篇本文介绍spring动态代理创建器自动创建动态代理的过程。本文介绍spring代理的实现方式(jdk动态代理 & cglib动态代理);
2.动态代理简介
我们先熟悉下两种动态代理的实现方式;
A.jdk动态代理
- 定义一个接口Car(jdk动态代理类必须实现至少一个接口);
- 定义一个实现类Suv(被代理的目标类);
- 定义一个InvocationHandler实现类CarProxy(持有Suv对象的引用,实现接口中的invoke方法);
- 使用Proxy.newProxyInstance创建代理对象carProxy;
- 使用代理对象调用目标类的方法: carProxy.drive(“张三”);
/**
* 测试jdk动态代理
* 1.定义一个接口Car(jdk动态代理类必须实现至少一个接口)
* 2.定义一个实现类Suv(被代理的目标类)
* 3.定义一个InvocationHandler实现类CarProxy(持有Suv对象的引用,实现接口中的invoke方法)
* 4.使用Proxy.newProxyInstance创建代理对象carProxy
* 5.使用代理对象调用目标类的方法: carProxy.drive("张三")
*/
public interface Car {
void drive(String name);
/**
* 实现类
*/
@Slf4j
class Suv implements Car {
@Override
public void drive(String name) {
log.info("司机:{}开车", name);
}
}
/**
* 代理逻辑
*/
@Slf4j
class CarProxy implements InvocationHandler {
private final Car car;
public CarProxy(Car car) {
this.car = car;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("代理,目标方法运行之前");
Object rst = method.invoke(car, args);
log.info("代理,目标方法运行之后");
return rst;
}
}
static void main(String[] args) {
Car car = new Suv();
Class<?> cla = car.getClass();
//**创建动态代理
Car carProxy = (Car)Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), new CarProxy(car));
carProxy.drive("张三");
carProxy.toString();
}
}
B.cglib动态代理
- 定义一个类Suv(不用实现接口,当然也可以实现接口);
- 定义一个MethodInterceptor(Callback的子接口)实现类CarProxy;
- 使用Enhancer.create创建代理对象carProxy;
- 使用代理对象调用目标类的方法: carProxy.drive(“张三”);
/**
* 测试cglib动态代理
* 1.定义一个类Suv(不用实现接口,当然也可以实现接口)
* 2.定义一个MethodInterceptor(Callback的子接口)实现类CarProxy
* 3.使用Enhancer.create创建代理对象carProxy
* 4.使用代理对象调用目标类的方法: carProxy.drive("张三")
*/
@Slf4j
public class Suv {
public void drive(String name) {
log.info("司机:{}开车", name);
}
@Override
public String toString() {
log.info("suv toString");
return "suv";
}
/**
* 代理逻辑
* MethodInterceptor为Callback的子接口
*/
@Slf4j
static class CarProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
log.info("代理,目标方法运行之前");
Object rst = proxy.invokeSuper(obj, args);
log.info("代理,目标方法运行之后");
return rst;
}
}
public static void main(String[] args) {
//**创建动态代理
Suv carProxy = (Suv) Enhancer.create(Suv.class, new CarProxy());
carProxy.drive("张三");
carProxy.toString();
}
}
- cglib动态代理每一个代理逻辑就是一个Callback。创建代理类时,可同时定义多个Callback,然后通过CallbackFilter查找指定方法需执行的Callback;
/**
* 过滤器
* 使用CallbackHelper快速实现CallbackFilter
*/
public class CarFilter extends CallbackHelper {
public CarFilter(Class superclass, Class[] interfaces) {
super(superclass, interfaces);
}
@Override
protected Object getCallback(Method method) {
//**只代理drive方法
return "drive".equals(method.getName()) ? new CarProxy() : NoOp.INSTANCE;
}
}
public static void main(String[] args) {
//**创建动态代理,使用过滤器
CarFilter filter = new CarFilter(Suv.class, null);
Suv carProxy1 = (Suv) Enhancer.create(Suv.class, null, filter, filter.getCallbacks());
carProxy1.drive("李四");
carProxy1.toString();
}
3.动态代理实现
在上一步我们了解的动态代理的基本概念和实现方式,这里我们看一下spring如何使用jdk动态代理 & cglib动态代理创建动态代理类;
概念
- 是否静态的(TargetSource.isStatic()):
TargetSource是对原始bean的封装。每次调用TargetSource.getTarget()返回的原始bean都是同一个对象,则为true。一般是指原始bean为单例; - 是否暴露代理(AdvisedSupport.isExposeProxy()):
如果允许暴露代理,在执行目标方法的过程中会把代理对象设置到ThreadLocal中,可从该ThreadLocal获取当前执行的代理对象; - 是否冻结(AdvisedSupport.isFrozen()):
如果是冻结的,表示针对原始bean的拦截器链是固定不变的。即配置的aop代理是固定的,没有动态配置;
核心类图
核心类说明
A.AopProxy
创建动态代理接口,提供3个方法,创建创建代理bean和代理bean的class对象;
B.JdkDynamicAopProxy
- AopProxy的jdk动态代理实现,使用jdk动态代理创建代理bean和class;
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
...
//**使用jdk动态代理创建代理bean
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
@Override
public Class<?> getProxyClass(@Nullable ClassLoader classLoader) {
//**使用jdk动态代理创建代理bean的class对象
return Proxy.getProxyClass(classLoader, this.proxiedInterfaces);
}
- JdkDynamicAopProxy同时继承InvocationHandler,实现了invoke方法;
- 调用equals和hashCode方法
如果原始bean的接口定义了equals和hashCode方法,则直接调用原始bean的实现,否则调用JdkDynamicAopProxy的实现; - 调用Advised接口方法
转为调用Advised实例的方法。一般场景调用不到Advised接口的方法,可能使用反射可以调用; - 调用其它方法(原始bean的接口定义的方法)
先查找目标方法的代理配置。如果存在代理配置就调用代理逻辑,然后调用原始bean的目标方法。如果不存在就直接调用原始bean的目标方法;
- 调用equals和hashCode方法
@Override
@Nullable //**如果可能会返回null,加上这个标识,提示调用者
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {//**如果接口没有定义equals和hashCode方法,则调用此类的equals和hashCode方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
//**没发现实际用处
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
//**调用Advised接口的方法
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//**把代理对象设置到ThreadLocal中
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//**获取原始bean和class对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//**查找调用方法的拦截
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {//**如果Interceptor列表为空,直接调用目标方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {//**调用Interceptor链(依次调用每个Interceptor)
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
//**处理返回值类型
return retVal;
}
finally {
//**释放资源
}
}
C.CglibAopProxy
AopProxy的cglib动态代理实现,使用cglib动态代理创建代理bean和class。创建代理bean的核心代码;
- 创建Enhancer(用于创建cglib动态代理bean);
- 获取Callback(把代理逻辑封装成Callback);
- 设置CallbackFilter(CallbackFilter可以查找指定方法需执行的Callback);
- 创建代理bean/class;
//**创建代理bean和class的核心逻辑
private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly) {
try {//**获取&验证原始bean的class对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
//**如果原始bean仍然是cglib代理bean,获取上一级的原始bean和接口
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
//**验证原始bean的方法是否支持cglib代理,不符合也只是打印日志而已
validateClassIfNecessary(proxySuperClass, classLoader);
//**创建Enhancer(用于创建cglib动态代理bean)
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader smartClassLoader &&
smartClassLoader.isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setAttemptLoad(true);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
//**获取Callback(把代理逻辑封装成Callback)
Callback[] callbacks = getCallbacks(rootClass);
//**获取Callback的class对象
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
//**设置CallbackFilter(CallbackFilter可以查找指定方法需执行的Callback)
//**ProxyCallbackFilter是一个CallbackFilter的实现,内部类&私有,外部无法访问
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//**创建代理bean/class
return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));
}
//**异常处理
}
根据原始bean的class对象获取Callback列表;
- 创建创建Callback数组。调用代理bean的目标方法时,会根据CallbackFilter过滤。根据使用场景分类如下:
- 支持目标方法有一个/多个代理配置
调用时会按顺序调用拦截器链,最后调用原始bean的目标方法;- DynamicAdvisedInterceptor,默认的Callback。支持TargetSource和拦截器链是动态的,调用目标方法时才会获取TargetSource和拦截器链;
- FixedChainStaticTargetInterceptor,静态的Callback。TargetSource和拦截器链必须是固定不变的,创建时就会初始化,调用时直接使用初始化的TargetSource和拦截器链;
- 目标方法没有任何代理配置
原始bean的任何方法配置了代理,就会创建代理bean,但是有些方法是没有配置代理的,不需要调用其它代理逻辑;- StaticUnadvisedExposedInterceptor & StaticUnadvisedInterceptor适用于静态TargetSource & 无代理配置。前者会暴露代理;
- DynamicUnadvisedExposedInterceptor & DynamicAdvisedInterceptor适用于动态TargetSource & 无代理配置。前者会暴露代理;
- 目标调度程序,会把调用转发给其它对象
StaticDispatcher & AdvisedDispatcher,前者转发给原始bean,后者转发给AdvisedSupport; - Spring针对固定方法生成默认的代理逻辑
EqualsInterceptor & HashCodeInterceptor,支持equals和HashCode方法调用的Callback;
- 支持目标方法有一个/多个代理配置
- 针对静态的(原始bean为单例) & 冻结的(Advice链是固定的),则进行一些优化。避免调用目标方法时动态去过滤需要执行的Callback;
- 为每个目标方法创建一个固定的Callback(FixedChainStaticTargetInterceptor)。即每个方法都有一个Callback;
- 把所有的FixedChainStaticTargetInterceptor添加到Callback数组的末尾;
- 记录每个方法对应FixedChainStaticTargetInterceptor在Callback数组的索引;
- 进行上述优化的好处: 调用目标方法时可以直接根据索引找到Callback,避免进行额外的查找;
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
//**代理配置: 是否暴露代理
boolean exposeProxy = this.advised.isExposeProxy();
//**代理配置: 是否冻结
boolean isFrozen = this.advised.isFrozen();
//**否是静态的(每次调用getTarget()返回的原始bean都是同一个对象,一般是指原始bean为单例)
boolean isStatic = this.advised.getTargetSource().isStatic();
//**开始创建Callback数组,每个Callback元素处理一种类型。调用代理bean的目标方法时,会根据CallbackFilter查找Callback
/**
* 1.DynamicAdvisedInterceptor,适用于执行设置了aop拦截的目标方法
* DynamicAdvisedInterceptor会按顺序调用拦截器链,最后调用原始bean的目标方法
**/
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
/**
* 以下的4个Callback都是适用于直接执行原始bean的目标方法,没有代理逻辑。
* 前两个和后两个的区别:后两个次调用时需要先调用this.targetSource.getTarget()获取原始bean
* 2.StaticUnadvisedExposedInterceptor,StaticUnadvisedInterceptor
* 适用于静态TargetSource的Callback,区别就是是否暴露代理
* 3.DynamicUnadvisedExposedInterceptor,DynamicAdvisedInterceptor
* 适用于非静态TargetSource的Callback,区别就是是否暴露代理
**/
Callback targetInterceptor;
if (exposeProxy) { //**如果允许暴露代理,在执行目标方法的过程中会把代理对象设置到ThreadLocal中
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
//**静态目标调度程序,直接转发给原始bean
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
//**主要的Callback数组
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, //**默认的Callback
targetInterceptor, //**直接调用原始bean的Callback
new SerializableNoOp(), //**空Callback。Callback不支持空值,以此代替空值
targetDispatcher, this.advisedDispatcher, //**目标调度程序,前者转发给原始bean,后者转发给AdvisedSupport
new EqualsInterceptor(this.advised), //**支持equals方法的Callback
new HashCodeInterceptor(this.advised) //**支持hashCode方法的Callback
};
Callback[] callbacks;
/**
* 如果是静态的(原始bean为单例) & 是冻结的(Advice链是固定的),则进行优化
* 1.查找每个方法的拦截器链,并封装为FixedChainStaticTargetInterceptor。即每个方法都有一个FixedChainStaticTargetInterceptor
* 2.把所有的FixedChainStaticTargetInterceptor添加到Callback数组的末尾
* 3.记录每个方法对应FixedChainStaticTargetInterceptor在Callback数组的索引
* 进行上述优化的好处: 调用目标方法时可以直接根据索引找到Callback,避免进行额外的查找
**/
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
创建代理bean/class的逻辑,创建实例使用到原始bean的构造器和参数;
//**创建代理bean的class对象
protected Class<?> createProxyClass(Enhancer enhancer) {
enhancer.setInterceptDuringConstruction(false);
return enhancer.createClass();
}
//**创建代理bean
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
//**设置Callback(代理逻辑)
enhancer.setCallbacks(callbacks);
//**使用构造器和参数创建代理bean
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}