本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1、private、final、static修饰的方法不能够被动态代理
final修饰的关键字不可变,不可继承不可重写。接口继承都不行
static不能修饰接口中的方法可以修饰抽象类的方法,static修饰的方法不能被继承
private修饰的方法不能被继承,子类都访问不到。接口实现类同样也访问不到
2、由于生成的代理类已经继承了proxy,所以只能通过实现接口来实现动态代理
3、java中不支持多继承的原因,因为如果两个父类有相同的方法,不同的实现子类再调用这个方法是根本就不知道调用哪一个。而接口可以有相同的实现,其方法在没有实现之前是没有意义的,实现的方法必须要实现。接口也算一种重写。
public class Mao implements Hummer {
@Override
public void init() {
}
}
Spring中不支持直接对接口动态代理,因为Spring中的动态代理是在Bean实例化之后,而接口根本就实例化不了,Mybatis却可以,因为它走的不是Spring动态代理这一套逻辑
我们写的通知,如何实现的呢?
实际上切面类中的通知会被注册成一个通知,然后保存到一个集合中,每次扫描到Bean回去检查这个Bean能否匹配上切点,如果可以说明需要被增强,Cglib来说需要传入 MethodInterceptor调用invoke方法,该类的每一个方法都会调用 MethodInterceptor.intercept方法。内部会根据传入的方法,获取到匹配上的通知集合,如果为0直接调用方法不走通知,不为0,生成一个拦截器链执行通知方法,实际上是通过递归的方式,通过切面类反射执行通知方法。joinpoint.process就是执行下一个拦截器
实际上就是生成增强后的字节码文件然后通过类加载器加载。创建出代理对象。如何生成这个字节码文件的呢?
// 原代码
public class DynamicProxyTest {
interface IHello {
void sayHello();
}
static class Hello implements IHello {
@Override
public void sayHello() {
System.out.println("hello world");
}
}
// 代理对象需要invocationHandler作为构造函数,因为他需要通过这个方法调用增强后的方法
static class DynamicProxy implements InvocationHandler {
Object originalObj;
Object bind(Object originalObj){
this.originalObj = originalObj;
return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),
originalObj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Like mao");
return method.invoke(originalObj,args);
}
}
}
// 代理后代码 可以看出实际上是通过反射去调用方法的,对象则是InvocationHandler对象
// 通过静态代码块获取对应的方法对象。反射调用执行。
// 可以看出所有的代理对象都继承Proxy实现原接口。(Proxy对象持有InvocationHandler对象。而这个对象invoke是我们编写的增强逻辑)
// 此外特别的一个点是因为代理对象继承了Proxy所以只能通过实现接口的方式(不支持多继承)
final class $Proxy0 extends Proxy implements IHello {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void sayHello() throws {
try {
// super.h 实际上就是InvocationHandler对象
// 对于每一个方法都调用这个逻辑,而通过将传入的methed对象传入invoke增强了每一个方法。
super h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
// 类加载时获取需要代理的方法、默认是需要将equals、tostring、hashcode方法
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals");
// 这里获取的是接口方法
m3 = Class.forName("DynamicProxyTest$IHello").getMethod("sayHello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
// 生成类,获取增强后的类
Class cl = getProxyClass(loader, interfaces);
try {
// 将invocationHandler作为构造参数实例化代理对象
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
} catch (IllegalAccessException e) {
throw new InternalError(e.toString());
} catch (InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
}
// 生成字节码的代码
private byte[] generateClassFile() {
//第一步, 将所有的方法组装成ProxyMethod对象
//首先为代理类生成toString, hashCode, equals等代理方法
addProxyMethod(hashCodeMethod, Object.class);
addProxyMethod(equalsMethod, Object.class);
addProxyMethod(toStringMethod, Object.class);
//遍历每一个接口的每一个方法, 并且为其生成ProxyMethod对象,
for (int i = 0; i < interfaces.length; i++) {
// 可以看出这里只获取接口的方法,并不是其他类
Method[] methods = interfaces[i].getMethods();
for (int j = 0; j < methods.length; j++) {
// 添加到代理方法中
addProxyMethod(methods[j], interfaces[i]);
}
}
//对于具有相同签名的代理方法, 检验方法的返回值是否兼容
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
checkReturnTypes(sigmethods);
}
//第二步, 组装要生成的class文件的所有的字段信息和方法信息
try {
//添加构造器方法
methods.add(generateConstructor());
//遍历需要添加的方法
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
for (ProxyMethod pm : sigmethods) {
fields.add(new FieldInfo(pm.methodFieldName,
"Ljava/lang/reflect/Method;", ACC_PRIVATE | ACC_STATIC));
//添加代理类的代理方法
methods.add(pm.generateMethod());
}
}
//添加代理类的静态字段初始化方法
methods.add(generateStaticInitializer());
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
//验证方法和字段集合不能大于65535
if (methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
}
if (fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
}
//第三步, 写入最终的class文件
//验证常量池中存在代理类的全限定名
cp.getClass(dotToSlash(className));
//验证常量池中存在代理类父类的全限定名, 父类名为:"java/lang/reflect/Proxy"
cp.getClass(superclassName);
//验证常量池存在代理类接口的全限定名
for (int i = 0; i < interfaces.length; i++) {
cp.getClass(dotToSlash(interfaces[i].getName()));
}
//接下来要开始写入文件了,设置常量池只读
cp.setReadOnly();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
try {
//1.写入魔数
dout.writeInt(0xCAFEBABE);
//2.写入次版本号
dout.writeShort(CLASSFILE_MINOR_VERSION);
//3.写入主版本号
dout.writeShort(CLASSFILE_MAJOR_VERSION);
//4.写入常量池
cp.write(dout);
//5.写入访问修饰符
dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
//6.写入类索引
dout.writeShort(cp.getClass(dotToSlash(className)));
//7.写入父类索引, 生成的代理类都继承自Proxy
dout.writeShort(cp.getClass(superclassName));
//8.写入接口计数值
dout.writeShort(interfaces.length);
//9.写入接口集合
for (int i = 0; i < interfaces.length; i++) {
dout.writeShort(cp.getClass(dotToSlash(interfaces[i].getName())));
}
//10.写入字段计数值
dout.writeShort(fields.size());
//11.写入字段集合
for (FieldInfo f : fields) {
f.write(dout);
}
//12.写入方法计数值
dout.writeShort(methods.size());
//13.写入方法集合
for (MethodInfo m : methods) {
m.write(dout);
}
//14.写入属性计数值, 代理类class文件没有属性所以为0
dout.writeShort(0);
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
//转换成二进制数组输出
return bout.toByteArray();
}
1、代理对象class文件最重要的就是方法和字段了
1、收集所有接口的抽象方法,封装成抽象方法 2、遍历每一个抽象方法生成对应字段、以及方法信息
// 字段
private static Method m0;
// 方法信息
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
// 最后开始组装class 比如魔数、版本号、方法、字段、修饰符等等,然后生成字节码文件
获取动态代理生成的class文件
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\Users\50213\Desktop\class");
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Cglib动态代理生成的代理对象class。會為每一個方法生成一個原有方法,和代理方法MethodProxy。
Cglib和JDK的底層不同的是,前者通過對象調用方法形式實現,而後者通過反射實現。
Cglib創建代理對象會生成三個類,一個代理類,兩個FastClass類。
FastClass説白了就是將方法名與方法調用做一個映射,
@Override
// 这里传进来的obj是代理对象
// method,目标对象的方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 说白了这种方式实际走的还是反射srcTarget原对象
Object o = method.invoke(srcTarget, args);
// 这里就是直接通过父类调用原方法,性能高。内部是通过switch来确定到底调用哪一个方法
proxy.invokeSuper(obj,args);
return o;
}
// 下面两种方式的区别
// MethodProxy的两个方法
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// 这里调用的fastClass 而这个回调了getPeriod,这样做会又会调用回自己进入死循环
// i1是增强后方法的下标
return fci.f1.invoke(fci.i1, obj, args);
}
}
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// 这里调用的fastClass 实际上回调了CGLIB$getPeriod$1()
// i2是未增强的下标,作为switch(int num)
return fci.f2.invoke(fci.i2, obj, args);
}
}
public class hotTask$$EnhancerBySpringCGLIB$$52b7866f extends hotTask implements SpringProxy, Advised, Factory {
private boolean CGLIB$BOUND;
// 线程相关的回调函数
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
// 静态可以用来保存代理对象共有的回调函数
private static final Callback[] CGLIB$STATIC_CALLBACKS;
// 用户定义的回调函数,回调函数不是静态的所以每一次创建对象都需要对回调函数赋值
private MethodInterceptor CGLIB$CALLBACK_0;
// 这些也是回调函数
private MethodInterceptor CGLIB$CALLBACK_1;
// 會為每一個方法生成一個原有方法,和代理方法MethodProxy。
private static final Method CGLIB$getPeriod$1$Method;
private static final MethodProxy CGLIB$getPeriod$1$Proxy;
// 在下方静态代码块自动执行
static void CGLIB$STATICHOOK29() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
// 生成的代理对象class对象
Class var0 = Class.forName(
"com.qianqi.community.quartz.task.hotTask$$EnhancerBySpringCGLIB$$52b7866f"
);
...
Method[] var10000 = ReflectUtils.findMethods(
new String[]{"getPeriod"...}, (
var1 = Class.forName("com.qianqi.community.quartz.JobBean"))
.getDeclaredMethods());
// 获取到target类中相应的方法对象
CGLIB$getPeriod$1$Method = var10000[0];
// 获取到代理类中相应的方法
CGLIB$getPeriod$1$Proxy = MethodProxy.create(var1, var0, "()I", "getPeriod", "CGLIB$getPeriod$1");
}
// 设置回调函数的方法,通过ThreadLocal进行设置的
public static void CGLIB$SET_THREAD_CALLBACKS(final Callback[] array) {
hotTask$$EnhancerByCGLIB$$6f07c3f7.CGLIB$THREAD_CALLBACKS.set(array);
}
// CGLIB$getPeriod$1$Method方法的具体实现
final int CGLIB$getPeriod$1() {
return super.getPeriod();
}
// CGLIB$getPeriod$1$Proxy方法的具体实现
public final int getPeriod() {
// 获取用户传入的回调函数
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
// 如果用户没有设置 从threadLocal || static 获取回调函数
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
// 调用回调函数的intercept方法,传入this,原方法,空参,代理后的方法
// callable中是MethodInterceptor
Object var1 = var10000.intercept(
this,
CGLIB$getPeriod$1$Method,
CGLIB$emptyArgs,
CGLIB$getPeriod$1$Proxy
);
// 参数返回null,返回0
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
// 最后没有回调方法,则调用父类的原逻辑
return super.getPeriod();
}
}
// 回调函数初始化,参数是代理对象
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
hotTask$$EnhancerBySpringCGLIB$$52b7866f var1 =
(hotTask$$EnhancerBySpringCGLIB$$52b7866f)var0;
// 只绑定一次
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
// 首先从ThreadLocal中获取
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
// 静态获取
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
// 一般用不怎么到
Callback[] var10001 = (Callback[])var10000;
// 固定的那几个处理函数
var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];
var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];
var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];
var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];
var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];
var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
// 执行拦截器链的MethodIntercept
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
}
}
static {
CGLIB$STATICHOOK29();
}
public class hotTask$$EnhancerBySpringCGLIB$$52b7866f$$FastClassBySpringCGLIB$$ea58f146 extends FastClass{
// 这个invoke调用的是上面那个类的var10000.CGLIB$run$0();增强方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
52b7866f var10000 = (52b7866f)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.run();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
...
case 11:
return new Integer(var10000.getPeriod());
case 12:
return var10000.getDescription();
case 13:
var10000.CGLIB$run$0();
return null;
case 16:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
}
}
}
}
Spring中AOP的实现
package org.springframework.aop.framework;
import java.io.Serializable;
import java.lang.reflect.Proxy;
import org.springframework.aop.SpringProxy;
import org.springframework.core.NativeDetector;
import org.springframework.util.ClassUtils;
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
private static final long serialVersionUID = 7930414337282325166L;
public DefaultAopProxyFactory() {
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// isOptimize()判断是否需要进行优化,较早的版本,CGLIB的效率比JDK要好
// isProxyTargetClass是否为类进行动态代理
if (NativeDetector.inNativeImage() || !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) && !ClassUtils.isLambdaClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
// 是否添加了接口,如果没有添加使用Cglib
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
}
}
JdkDynamicAopProxy
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
/** Config used to configure this proxy. */
private final AdvisedSupport advised;
private final Class<?>[] proxiedInterfaces;
// 接口中是否定义了equals,默认false
private boolean equalsDefined;
// 接口是否定义了hashCode,默认false
private boolean hashCodeDefined;
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;
// 当前类需要代理的接口,还会额外代理3个接口,SpringProxy,Advised和DecoratingProxy
// DecoratingProxy用于获取代理对象的原对象
// SpringProxy只是一个标记接口,标记代理对象是使用spring aop创建
// Advised,实现该接口,允许代理对象动态添加通知
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
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 {
// 如果接口中没有定义euqals,交给代理比较,实际上就是不拦截
// 如果接口定义了那么,则会通过拦截后再调用
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
// DecoratingProxy接口中定义了一个方法getDecoratedClass,用来获取被代理的原始目标对象的类型
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 调用AopProxyUtils工具类的方法,内部通过循环遍历的方式,找到最原始的被代理的目标类
return AopProxyUtils.ultimateTargetClass(this.advised);
}
// 调用的方法是Advised接口定义的方法时,走到这里执行
方法来源于 Advised 接口,代理对象默认情况下会实现 Advised 接口,可以通过代理对象来动态向代理对象中添加通知等
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//是否需要在threadLocal中暴露代理对象
if (this.advised.exposeProxy) {
// 将当前代理对象暴露在上下文中,在当前线程中可以通过静态方法
// AopContext#currentProxy获取当前被暴露的动态代理
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取当前方法的拦截器对象
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())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
// 如果返回值为null,但方法返回类型为基本数据类型,无法转换抛出异常
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 {
// isStatic为true,表示目标对象是单例的,同一个代理对象中所有方法共享一个目标对象
// isStatic为false的时候,通常每次调用代理的方法,target对象是不一样的,所以方法调用之后需要进行释放,可能有些资源清理,连接的关闭等操作
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
// 恢复原来ThreadLocal中的代理对象
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
@Override
public boolean equals(@Nullable Object other) {
...
}
@Override
public int hashCode() {
...
}
}
ObjenesisCglibAopProxy
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
// 获取被代理的类
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
// 如果被代理的类时cglib创建的类
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
// 将其父类最为被代理的类
proxySuperClass = rootClass.getSuperclass();
// 获取父类的接口
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 设置代理的父类
enhancer.setSuperclass(proxySuperClass);
// 设置被代理的接口[开发者硬编码指定的需要被代理的接口列表,SpringProxy,Advised],这个比jdk动态代理的方式少了一个DecoratingProxy接口
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
// 命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 字节码生成策略
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 每一个方法的执行器链、rootClass,包括实现的接口的方法
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
}
getCallbacks
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// 是否将代理对象暴露在threadlocal
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
// 代理对象是否是单例
boolean isStatic = this.advised.getTargetSource().isStatic();
// 方法上有需要执行的拦截器时,会调用这个方法来处理
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// 没有拦截器需要执行时,通过这个处理,内部通过反射调用目标对象的方法
Callback targetInterceptor;
if (exposeProxy) {
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()));
}
// 直接调用目标对象
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // 处理匹配到拦截器的方法
targetInterceptor, // 处理未匹配到拦截器的方法,并且方法返回值为目标对象类型用这个,返回代理后的对象
new SerializableNoOp(),
targetDispatcher, // 处理未匹配到拦截器的方法
this.advisedDispatcher, // 处理Advised接口中定义的方法
new EqualsInterceptor(this.advised), // 处理equals方法
new HashCodeInterceptor(this.advised) // 处理hashCode方法
};
Callback[] callbacks;
// 如果被代理的对象冻结的,生成好的代理中通知不可改变
// 提前将每一个方法对应的拦截器链缓存起来
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;
}
ProxyCallbackFilter.accept
// 主要是根据method匹配mainCallbacks中的拦截器
@Override
public int accept(Method method) {
if (AopUtils.isFinalizeMethod(method)) {
logger.trace("Found finalize() method - using NO_OVERRIDE");
return NO_OVERRIDE;
}
// Advised中的方法,返回值是自己。targetInterceptor
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (logger.isTraceEnabled()) {
logger.trace("Method is declared on Advised interface: " + method);
}
return DISPATCH_ADVISED;
}
// EqualsInterceptor(this.advised)
if (AopUtils.isEqualsMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'equals' method: " + method);
}
return INVOKE_EQUALS;
}
// HashCodeInterceptor(this.advised)
if (AopUtils.isHashCodeMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'hashCode' method: " + method);
}
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
// Proxy is not yet available, but that shouldn't matter.
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// If exposing the proxy, then AOP_PROXY must be used.
if (exposeProxy) {
if (logger.isTraceEnabled()) {
logger.trace("Must expose proxy on advised method: " + method);
}
return AOP_PROXY;
}
// 从缓存中获取
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Method has advice and optimizations are enabled: " + method);
}
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
int index = this.fixedInterceptorMap.get(method);
return (index + this.fixedInterceptorOffset);
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Unable to apply any optimizations to advised method: " + method);
}
return AOP_PROXY;
}
}
else {
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
if (logger.isTraceEnabled()) {
logger.trace("Method return type is assignable from target type and " +
"may therefore return 'this' - using INVOKE_TARGET: " + method);
}
return INVOKE_TARGET;
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Method return type ensures 'this' cannot be returned - " +
"using DISPATCH_TARGET: " + method);
}
return DISPATCH_TARGET;
}
}
}
主要是拦截器对象
- DynamicAdvisedInterceptor
- StaticUnadvisedExposedInterceptor
- StaticUnadvisedInterceptor
- DynamicUnadvisedInterceptor
- StaticDispatcher
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
//代理配置信息
private final AdvisedSupport advised;
//构造器,需要一个AdvisedSupport
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
//这个方法是关键,用来处理代理对象中方法的调用
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//被暴露在threadLocal中旧的代理对象
Object oldProxy = null;
//用来标记代理对象是否被暴露在threadLocal中
boolean setProxyContext = false;
//目标对象
Object target = null;
//目标源
TargetSource targetSource = this.advised.getTargetSource();
try {
//代理配置中是否需要将代理暴露在threadLocal中
if (this.advised.exposeProxy) {
//将代理对象暴露出去
oldProxy = AopContext.setCurrentProxy(proxy);
//将setProxyContext置为true
setProxyContext = true;
}
//获取目标对象(即被代理的对象)
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//@1:获取当前方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//记录方法返回值
Object retVal;
//拦截器链不为空 && 方法是public类型的
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
//获取方法调用参数
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 直接调用目标对象的方法
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 创建一个方法调用器(包含了代理对象、目标对象、调用的方法、参数、目标类型、方法拦截器链)
// @2:并执行方法调用器的processd()方法,此方法会一次执行方法调用链,最终会调用目标方法,获取返回结果
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
// 处理方法返回结果:会根据方法返回值的类型,做一些处理,比如方法返回的类型为自己,则最后需要将返回值置为代理对象
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
// 目标对象不为null && 目标源不是静态的
//所谓静态的,你可以理解为是否是单例的
// isStatic为true,表示目标对象是单例的,同一个代理对象中所有方法共享一个目标对象
// isStatic为false的时候,通常每次调用代理的方法,target对象是不一样的,所以方法调用万之后需要进行释放,可能有些资源清理,连接的关闭等操作
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
// setProxyContext为ture
if (setProxyContext) {
// 需要将旧的代理再放回到上线文中
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
Cglib高级操作
public class Service1 {
public void m1(){
System.out.println("m1");
this.m2();
}
public void m2(){
System.out.println("m2");
}
public Service1 getService1(){
return this;
}
}
@Test
public void testAop8(){
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(new Service1());
// 允许动态的添加修改通知
proxyFactory.addAdvice(new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println(String.format("进入%s方法",invocation.getMethod().getName()));
long startTime = System.nanoTime();
Object proceed = invocation.proceed();
long endTime = System.nanoTime();
System.out.println(endTime - startTime);
return proceed;
}
});
// 获取代理对象
Service1 proxy = (Service1)proxyFactory.getProxy();
/*
* 进入m1方法
m1
m2
6756129701
由于m2是this对象调用,并不是代理对象,如何让m2也是代理对象调用呢?
*/
proxy.m1();
// 可以获取到代理对象
System.out.println(proxy.getService1());
}
1、可以设置一个构造器指向自己,我可以尝试一下(这个没试过)
2、编写一个方法,返回Service1对象,因拦截方法会将其替换为代理对象这是一个特例(方法2不行,必须是代理对象的方法)
3、将代理对象暴露到ThreadLocal,这样就可以在目标对象中获取到代理对象了
4、可以设置一个外界方法设置一个属性,只不过这样不优雅
实例的创建
JDK
@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);
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// 在构造函数中将InvocationHandler传入
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);
}
}
Cglib
public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) {
// 实际上就是通过反射调用代理对象中的CGLIB$SET_THREAD_CALLBACKS方法设置回调方法
setThreadCallbacks(callbacks);
try {
// Explicit reference equality is added here just in case Arrays.equals does not have one
if (primaryConstructorArgTypes == argumentTypes ||
Arrays.equals(primaryConstructorArgTypes, argumentTypes)) {
// If we have relevant Constructor instance at hand, just call it
// This skips "get constructors" machinery
return ReflectUtils.newInstance(primaryConstructor, arguments);
}
// 创建代理对象
return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments);
}
finally {
// clear thread callbacks to allow them to be gc'd
setThreadCallbacks(null);
}
}
重点要使创建出来的代理对象能有正常功能,必须要走Spring AOP的这个流程,比如JDK需要在jdk构造函数中传入JdkDynamicAopProxy,不走这个流程就不会传入,调用invoke就会调用抛异常,甚至JDK都无法实例化,Cglib虽然可以实例化,但是没有设置setThreadCallBack就会导致调用方法时就会抛出异常,底层Cglib的调用还是通过CallBack调用(MethodIntercept)
总结
Cglib创建代理对象的过程以及调用过程
1、获取目标对象,如果目标对象也是一个代理对象,那么获取代理对象的superClass
2、通过Enhance创建代理对象,设置父类,设置接口(包含SpringProxy、Advise)获取回调函数CallBack(6个固定的MethodIntercept,主要处理接口以及执行拦截器链)
3、创建出代理对象
执行过程,会两个类fastClass,一个代理对象,fastClass主要是调用父类的方法,本质上是switch然后通过父类对象调用原方法,这点与JDK完全不同
代理对象会有一个静态代码块用于设置回调方法,我们执行代理方法是,实际上是调用MethodIntercept.intercept(代理对象,目标方法对象,参数,代理方法对象)
代理方法对象两个方法
invoke调用代理对象的方法,这样会造成死循环
invokeSuper调用父类方法
实际上方法最终的调用是通过CallBack完成的,它作为一个数组赋值给代理对象的属性,如果不对CallBack初始化调用时就会出现空指针异常,我就碰到过
JDK创建代理对象
JdkDynamicAopProxy本身就是一个InvocationHandler
1、获取目标对象上的接口,同时会添加3个接口SpringProxy、Advise、DecoratingProxy装饰代理
2、JDK创建代理对象那一套,Proxy.newProxyInstance(类加载器,实现的接口,this)
代理对象最终调用的都是InvocationHandler.invoke,这里同样有一个静态代码块通过反射获取所有的method对象,调用invoke(代理对象,目标对象方法,参数)
重点就是JdkDynamicAopProxy中的invoke方法了
1、首先判断是不是hashCode、equals等这些方法,如果有任何一个接口包含了这个两个方法,那么就会走拦截流程,否则直接调用代理对象提供的equals、hashcode方法
2、如果是DecoratingProxy调用相应类处理
3、Advise同理
4、如果允许代理对象暴露,那么会设置到ThreadLocal中,之后获取该方法的拦截器链,如果没有直接反射调用原方法,否则走拦截器链逻辑。这就是全过程。