Spring动态代理有两种:CGLIB动态代理和JDK动态代理。
JDK动态代理可以代理接口,不能代理没有实现接口的类;而CGLIB通过字节码技术可以动态生成被代理类的子类,从而可以代理没有实现接口的类;但是不能代理非public和final的方法,因为子类不可见。
Spring框架中使用DefaultAopProxyFactory来确定使用CGLIB或者JDK的动态代理
一般满足以下条件之一 就会进行CGLIB动态代理:
- optimize标志位被设定
- proxyTargetClass标志位被设定
- 设置了不代理接口
除此之外使用JDK动态代理
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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)) {
// 目标对象为接口或者是代理类时,使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
// 使用CGLIB动态代理
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
/**
* 确定代理的是不是接口
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
// 获取代理的接口
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
CGLIB动态代理
生成代理对象
ProxyFactory主要用来创建AOP代理,它继承了ProxyCreatorSupport,它的getProxy方法可以创建动态代理,并获取代理实例
public Object getProxy() {
// 调用父类ProxyCreatorSupport的方法
return createAopProxy().getProxy();
}
ProxyCreatorSupport是代理工厂的基类,通过他可以比较方便的访问可配置的AopProxyFactory
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 调用DefaultAopProxyFactory#createAopProxy创建AOP代理
return getAopProxyFactory().createAopProxy(this);
}
ProxyCreatorSupport#createAopProxy方法会调用DefaultAopProxyFactory#createAopProxy创建AOP代理,他会根据入参AdvisedSupport选择使用JDK或者CGLIB动态代理;
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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)) {
// JDK动态代理
return new JdkDynamicAopProxy(config);
}
// CGLIB动态代理
return new ObjenesisCglibAopProxy(config);
} else { // JDK动态代理
return new JdkDynamicAopProxy(config);
}
}
Spring AOP实现CGLIB动态代理主要的实现类是CglibAopProxy。首先DefaultAopProxyFactory#createAopProxy会调用CglibAopProxy构造方法创建CglibAopProxy实例
public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
// 必要的校验
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
// 设置通知配置信息
this.advised = config;
// 设置通知调度器
this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
ProxyFactory创建CglibAopProxy之后,接着调用它的getProxy方法创建代理。 由于CglibAopProxy实现了AopProxy接口,因此需要实现它的getProxy方法。在该方法中会获取代理类的信息,然后创建Enhancer并配置相关信息,再通过createProxyClassAndInstance方法来创建代理类和实例;
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 获取要代理的类
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// 因为要生成代理类的子类,所以这里为proxySuperClass
Class<?> proxySuperClass = rootClass;
// CGLIB_CLASS_SEPARATOR=$$
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
// 获取代理类的父类
proxySuperClass = rootClass.getSuperclass();
// 获取附加接口后将其加入到advise中
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 校验类信息
validateClassIfNecessary(proxySuperClass, classLoader);
// 配置 CGLIB Enhancer
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 获取回调,并将其Class复制到types数组中,这里的回调其实是拦截器
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// Encher设置回调过滤器和回调类型
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 产生代理类并创建代理实例
return createProxyClassAndInstance(enhancer, callbacks);
} catch (CodeGenerationException | IllegalArgumentException ex) { // final类或非public类,都不会创建代理
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
} catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
getProxy方法中会获取回调getCallbacks,该方法会设置AOP拦截器、目标拦截器、通知调度器等作为回调
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// 是否会为每次调用公开AOP代理
boolean exposeProxy = this.advised.isExposeProxy();
// 配置是否已冻结,并且不能进行任何更改
boolean isFrozen = this.advised.isFrozen();
// 每次调用是否返回相同的对象
boolean isStatic = this.advised.getTargetSource().isStatic();
// AOP代理拦截器:DynamicAdvisedInterceptor,拦截AOP的调用
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// 目标拦截器
Callback targetInterceptor;
// 根据exposeProxy参数设置不同的目标拦截器
if (exposeProxy) { // 每次调用公开AOP代理
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
} else { // 每次调用不公开AOP代理
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// 目标调度器
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
// 主要的回调,拦截器得数组
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // DynamicAdvisedInterceptor拦截器
targetInterceptor, // 如果被优化,可以不考虑advice直接调用目标
new SerializableNoOp(), // 不覆写映射到this的方法
targetDispatcher,
this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// 如果目标是静态的并且advice链被冻结了,我们可以通过使用那个方法的固定链直接调用目标对象,以此来优化调用
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);
// 一些小的内存优化(可以通过无advice来跳过方法的创建)
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);
}
// 把mainCallbacks和fixedCallbacks复制到callbacks数组
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;
}
ObjenesisCglibAopProxy是CglibAopProxy的子类,它覆写了其 createProxyClassAndInstance方法。该方法里面首先通过enhancer创建代理类,再创建代理类的实例对象
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// 利用enhancer创建代理类
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
// 如果在当前JVM上,配置的Objenesis实例化策略已经被识别为不工作或者spring.objenesis.ignore属性被设置为true,objenesis.isWorthTrying()会返回false
if (objenesis.isWorthTrying()) {
try {
// 使用objenesis实例化策略进行实例化
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
} catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, falling back to regular proxy construction", ex);
}
}
if (proxyInstance == null) {
// 通过默认构造器实例化
try {
// 根据参数获取有参或者是无参构造器
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
// 设置构造器为可访问
ReflectionUtils.makeAccessible(ctor);
// 使用构造器实例化
proxyInstance = (this.constructorArgs != null ? ctor.newInstance(this.constructorArgs) : ctor.newInstance());
} catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
// 设置回调
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
目标方法的拦截
动态代理的处理过程如下图所示:
在生成代理对象的阶段,CglibAopProxy#getProxy#getCallbacks获取回调拦截器的时候,会提前设置DynamicAdvisedInterceptor动态拦截器。DynamicAdvisedInterceptor是CglibAopProxy的静态内部类,实现了MethodInterceptor接口,它的intercept方法会在对目标方法进行调用前进行拦截,根据AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice获取方法的拦截器处理链,如果目标方法存在拦截器链时,会new CglibMethodInvocation, 在该对象中依次调用拦截器链,最后再对目标方法进行调用;
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
// 获取目标类
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取拦截器和动态拦截advice
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 检查是否拥有一个调用拦截器InvokerInterceptor:即,没有实际的advice,但是仅仅反射目标对象的调用。这种情况直接调用目标
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 适配参数。可以跳过创建一个MethodInvocation:直接调用目标。
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 调用目标方法
retVal = methodProxy.invoke(target, argsToUse);
} else {
// 有拦截器链的时候会创建CglibMethodInvocation,递归遍历方法的拦截器,再使用反射的方式调用目标方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 处理返回的结果
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
} finally {
// 释放目标对象
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
// 恢复老的代理
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
一般都会创建CglibMethodInvocation并调用它的proceed方法,CglibMethodInvocation也是CglibAopProxy的静态内部类,它继承了ReflectiveMethodInvocation,会调用父类的proceed方法处理目标方法调用,继承关系如下:
public Object proceed() throws Throwable {
try {
// 调用父类ReflectiveMethodInvocation方法
return super.proceed();
} catch (RuntimeException ex) { // 运行时异常直接抛出
throw ex;
} catch (Exception ex) {
if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
// Propagate original exception if declared on the target method
// (with callers expecting it). Always propagate it for Kotlin code
// since checked exceptions do not have to be explicitly declared there.
throw ex;
} else {
// Checked exception thrown in the interceptor but not declared on the
// target method signature -> apply an UndeclaredThrowableException,
// aligned with standard JDK dynamic proxy behavior.
throw new UndeclaredThrowableException(ex);
}
}
}
父类ReflectiveMethodInvocation#proceed方法,首先会递归获取方法的拦截器链中的每一个拦截器,依次调用它们的invoke方法,最后再使用反射的方式调用目标方法
public Object proceed() throws Throwable {
// index从-1开始,递归调用过程中会累加,直到递归完所有的方法拦截器
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 最后使用反射的方式调用目标方法
return invokeJoinpoint();
}
// 获取方法拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果是拦截器和动态方法匹配器
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 转化为指定的类型
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// 匹配上了,调用拦截器的invoke方法
return dm.interceptor.invoke(this);
} else {
// 没有匹配上,递归下一个
return proceed();
}
} else {
// 方法拦截器,调用它。Spring的事务拦截器等就是在这里调用的
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
JDK动态代理
生成代理对象
Spring AOP的JDK动态代理只能代理接口,它和CGLIB动态代理都是使用DefaultAopProxyFactory#createAopProxy创建AOP代理;
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
// 必要的校验
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
// 通知配置
this.advised = config;
// 获取完整的代理接口,会额外增加Advised,SpringProxy等接口的代理
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 根据equals和hashCode寻找代理的接口
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
不同的是,JDK动态代理的的实现类是JdkDynamicAopProxy;
如上图,JdkDynamicAopProxy实现了InvocationHandler和AopProxy接口,AopProxy#getProxy可以生成代理实例,InvocationHandler#invoke拦截目标方法,并发起调用;先来看看getProxy方法获取代理实例;
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 生成代理实例
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
Proxy#newProxyInstance方法可以根据获取当前代理类的构造方法,然后调用它的构造方法完成对象的实例化
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException {
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
// 安全校验
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 查找或者产生指定的代理类
Class<?> cl = getProxyClass0(loader, intfs);
// 使用指定的调用handler调用它的构造器
try {
// 安全校验
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 获取构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) { // 非public方法,授权访问
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 使用构造方法构造实例对象
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
目标方法的拦截
当调用目标方法时,JdkDynamicAopProxy#invoke会识别目标方法,然后获取它的拦截器链,调用拦截链,然后调用方法本身
@Override
@Nullable
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 {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 目标对象没有自己实现equals
return equals(args[0]);
} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 目标对象没有自己实现hashCode
return hashCode();
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 声明类为DecoratingProxy,返回最终的代理对象
return AopProxyUtils.ultimateTargetClass(this.advised);
} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 使用代理配置在ProxyConfig上的服务调用,通过反射调用目标对象
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// 使调用可用
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取目标类
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取当前方法对的拦截链(实现了MethodInterceptor的拦截器设置了该方法作为切入点)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) { //当前方法的拦截链为空
// 获取目标方法参数之后使用反射调用方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else { // 当前方法有拦截链——》拦截器存在
// 创建方法的调用对象
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 通过拦截链处理到连接点,这里会递归调用拦截器链,最后在使用反射调用目标方法
retVal = invocation.proceed();
}
// 获取返回类型
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
ReflectiveMethodInvocation#proceed的处理过程和CGLIB一样,会根据责任链模式,递归遍历所有的方法拦截器,然后调用方法本身
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)