1.代理模式分类
静态代理
-
被代理增加新的方法的时候代理类需要同步新增,实际上是违背开闭原则的,仅能代理一类对象。
- 例如
Thread
就应用到了静态代理模式。
- 例如
动态代理
-
运行时动态生成代码,取消了对被代理类的扩展限制,遵循开闭原则。
-
若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成,无需修改代理类代码。
- JDKProxy
- Cglib
2.动态代理分析对比
2.1 JDK Proxy
Proxy生成代理类对象
// 参数一,被代理对象的classLoad,【需要加载新生成的类】
// 参数二,被代理对象的接口
// 参数三,处理器对象用来拦截代理对象方法执行
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);
}
// 获取代理类的构造函数,参数是处理器对象InvocationHandler数组【使用InvocationHandler的invoke方法进行拦截代理类方法的执行】
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;
}
});
}
// 反射一个代理对象
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);
}
}
代理类代码分析
-
利用内存中的对象字节码生成一个新的class文件
public static void main(String[] args) throws Exception { Object instance = new JDKMeipo().getInstance(new Girl()); Method findLove = instance.getClass().getMethod("findLove"); findLove.invoke(instance); byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class}); FileOutputStream os = new FileOutputStream("/Users/tiangeer/CodeStudy/java/design_patterns/src/main/java/com/tianyi/design/pattern/proxy/dynamicProxy/$Proxy0.class"); os.write(bytes); os.close(); }
-
代理类代码
import com.tianyi.design.pattern.proxy.staticProxy.Person; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; // 继承了被代理类接口 public final class $Proxy0 extends Proxy implements Person { private static Method m1; private static Method m3; private static Method m2; private static Method m0; // 接受一个InvocationHandler作为构造函数参数,印证了 Proxy.newProxyInstance()中的代理对象生成 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 findLove() throws { try { // 执行的就是InvocationHandler invoke方法。拦截代理对象的findLove方法 // 传入findLove方法类和参数,这里印证了ivvoke方法的Method参数是被执行方法 // 第一个参数是代理对象 // 第三个是参数列表 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); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); // 静态代码块中反射获取被代理对象接口的方法对象 m3 = Class.forName("com.tianyi.design.pattern.proxy.staticProxy.Person").getMethod("findLove"); 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()); } } }
-
JDK Proxy生成对象步骤
-
拿到被代理对象的引用,并且获取到它的所有的接口,反射获取;
-
JDK Proxy 类重新生成一个新的类、同时新的类要实现被代理类所有实现的所有的接口;
-
接口数不能超过 65535个
if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); }
- 这个限制是因为
接口索引计数器(interfaces_count)
,占2字节16个bit位,所以最多只能2^16=65535
- 这个限制是因为
-
-
动态生成 Java 代码,把新加的业务逻辑方法由一定的逻辑代码去调用(在代码中体现);
-
编译新生成的Java对吗.class
-
再重新加载到JVM中运行
-
整个过程叫做字节码重组
-
2.2Cglib Proxy
使用方式
public class CglibMeipo implements MethodInterceptor {
public Object getInstance(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
// 指定回调(拦截器)MethodInterceptor 实现了 Callback
enhancer.setCallback(this);
return enhancer.create();
}
// 拦截器
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
// 会死循环 ,因为会调用被代理方法 然后被代理方法中会调用此拦截器[intercept]
// Object o1 = methodProxy.invoke(o, objects);
Object o1 = methodProxy.invokeSuper(o, objects);
after();
return o1;
}
private void before() { System.out.println("前置");}
private void after() {System.out.println("后置");}
}
代理类代码分析
-
输出代理类
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"/Users/tiangeer/CodeStudy/java/design_patterns/src/main/java/com/tianyi/design/pattern/proxy/dynamicProxy/cglibProxy/cglib_proxy_classes"); Object instance = new CglibMeipo().getInstance(Customer.class); instance.getClass() .getMethod("findLove") .invoke(instance); }
-
代理类代码
- 第一个是代理类的 FastClass
- 第二个是代理类
- 第三个是被代理的FastCLASs
// 代理类继承了 Customer
public class Customer$$EnhancerByCGLIB$$bc53a8cc extends Customer implements 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 static final Method CGLIB$findLove$0$Method;
private static final MethodProxy CGLIB$findLove$0$Proxy;
. . . 其他方法和MethodProxy
static void CGLIB$STATICHOOK1() {
// 在静态代码块中重写了被代理对象类的所有方法。并且会有MethodProxy与之对应。
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
// var0 代理类
Class var0 = Class.forName("com.gupaoedu.vip.pattern.proxy.dynamicproxy.cglibproxy.Customer$$EnhancerByCGLIB$$bc53a8cc");
// var1 被代理类
Class var1;
CGLIB$findLove$0$Method = ReflectUtils.findMethods(new String[]{"findLove", "()V"}, (var1 = Class.forName("com.gupaoedu.vip.pattern.proxy.dynamicproxy.cglibproxy.Customer")).getDeclaredMethods())[0];
// 这里结合MethodProxy源码分析
CGLIB$findLove$0$Proxy = MethodProxy.create(var1, var0, "()V", "findLove", "CGLIB$findLove$0");
. . . 重写其他 Method 和 MethodProxy
/**
// 结合 MethodProxy的create源码来看,
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy();
proxy.sig1 = new Signature(name1, desc);
proxy.sig2 = new Signature(name2, desc);
proxy.createInfo = new CreateInfo(c1, c2);
return proxy;
}
public CreateInfo(Class c1, Class c2) {
// c1代理类
this.c1 = c1;
// c2被代理类
this.c2 = c2;
AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
if (fromEnhancer != null) {
this.namingPolicy = fromEnhancer.getNamingPolicy();
this.strategy = fromEnhancer.getStrategy();
this.attemptLoad = fromEnhancer.getAttemptLoad();
}
}
// createInfo的c1保存的是 代理类class c2保存的是被代理类class
// 在第一次调用【invokeSuper】时才生成FastClass
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
this.init();
FastClassInfo fci = this.fastClassInfo;
// 调用的是被代理的方法
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
}
}
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
this.init();
FastClassInfo fci = this.fastClassInfo;
// 调用的是代理方法,
// 所以如果在拦截器 【MethodInterceptor】的【intercept】调用此方法就会递归调用死循环 代理方法->拦截器->mrthodProxy.invoke->代理方法 ...
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
} catch (IllegalArgumentException var5) {
if (this.fastClassInfo.i1 < 0) {
throw new IllegalArgumentException("Protected method: " + this.sig1);
} else {
throw var5;
}
}
}
private void init() {
if (this.fastClassInfo == null) {
synchronized(this.initLock) {
if (this.fastClassInfo == null) {
CreateInfo ci = this.createInfo;
FastClassInfo fci = new FastClassInfo();
// 缓存中有就取出,没有就生成新的FastClass
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
// 获取方法的 index
fci.i1 = fci.f1.getIndex(this.sig1);
fci.i2 = fci.f2.getIndex(this.sig2);
this.fastClassInfo = fci;
}
}
}
}
private static FastClass helper(CreateInfo ci, Class type) {
FastClass.Generator g = new FastClass.Generator();
g.setType(type);
g.setClassLoader(ci.c2.getClassLoader());
g.setNamingPolicy(ci.namingPolicy);
g.setStrategy(ci.strategy);
g.setAttemptLoad(ci.attemptLoad);
// 缓存获取或者新生成
return g.create();
}
public static class Generator extends AbstractClassGenerator {
private static final AbstractClassGenerator.Source SOURCE;
private Class type;
public Generator() {
super(SOURCE);
}
}
protected static class Source {
String name;
// 缓存
Map cache = new WeakHashMap();
public Source(String name) {
this.name = name;
}
}
*/
}
// 被代理方法(MethodProxy.invokeSuper会调用)
final void CGLIB$findLove$0() {
super.findLove();
}
// 代理方法(methodProxy.invoke方法会调用。这里会调用类拦截器的intercept方法)
public final void findLove() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
// 调用拦截器 【MethodInterceptor】的intercept方法,对代理方法进行拦截
// 在拦截器中调用【MethodProxy.invokeSuper】调用被代理方法 【this是代理类】
var10000.intercept(this, CGLIB$findLove$0$Method, CGLIB$emptyArgs, CGLIB$findLove$0$Proxy);
} else {
super.findLove();
}
}
. . .
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
// 设置拦截器
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
. . .
}
被代理类FastClass
public class Customer$$FastClassByCGLIB$$2669574a extends FastClass {
public Customer$$FastClassByCGLIB$$2669574a(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch (var10000.hashCode()) {
case -1725733088:
if (var10000.equals("getClass()Ljava/lang/Class;")) {
return 7;
}
break;
case -1026001249:
if (var10000.equals("wait(JI)V")) {
return 1;
}
break;
case 243996900:
if (var10000.equals("wait(J)V")) {
return 2;
}
break;
case 946854621:
if (var10000.equals("notifyAll()V")) {
return 9;
}
break;
case 1116248544:
if (var10000.equals("wait()V")) {
return 3;
}
break;
case 1192015562:
if (var10000.equals("findLove()V")) {
return 0;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 4;
}
break;
case 1902039948:
if (var10000.equals("notify()V")) {
return 8;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 5;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 6;
}
}
}
// 根据index直接定位并执行方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
Customer var10000 = (Customer)var2;
int var10001 = var1;
try {
switch (var10001) {
case 0:
var10000.findLove();
return null;
case 1:
var10000.wait(((Number)var3[0]).longValue(), ((Number)var3[1]).intValue());
return null;
case 2:
var10000.wait(((Number)var3[0]).longValue());
return null;
case 3:
var10000.wait();
return null;
case 4:
return new Boolean(var10000.equals(var3[0]));
case 5:
return var10000.toString();
case 6:
return new Integer(var10000.hashCode());
case 7:
return var10000.getClass();
case 8:
var10000.notify();
return null;
case 9:
var10000.notifyAll();
return null;
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
}
```
- 方法执行顺序
- 代理方法->拦截器->mrthodProxy.invokeSuper()->被代理方法
#### 2.2.1 Cglib Proxy原理
> 为代理类和被代理类各生成一个Class,这个Class会为代理类和被代理类的方法分配一个idnex(int类型)。这个index当做一个入参,FastClass就可以直接定位到要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比JDK动态代理通过反射调用高
3. 两种代理方式对比
- JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
- JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
- JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法,CGLib 执行效率更高[但是生成效率低]。
- CGlib如果被代理的方法是final或者private的就GG了。
4.Spring中的动态代理
ProxyFactoryBean 核心的方法就是 getObject()方法
ProxyFactoryBean源码
@Nullable
public Object getObject() throws BeansException {
this.initializeAdvisorChain();
// private boolean singleton = true; 【不作任何配置默认就是单例】
if (this.isSingleton()) {
// 生成单例对象
return this.getSingletonInstance();
} else {
if (this.targetName == null) {
this.logger.info("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
}
// 生成多例
return this.newPrototypeInstance();
}
}
DefaultAopProxyFactory源码
// 默认Aop代理工厂
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
public DefaultAopProxyFactory() {
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
// 默认使用的是JDK代理
// private boolean optimize = false;
// private boolean proxyTargetClass = false;
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 {
// 根据有不有接口和是不是proxy对象决定使用Cglib代理还是JdkDynamic代理
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]);
}
}
类关系图
总结
- 当Bean实现了接口时,Spring选择JDK动态代理;
- 当Bean 没有实现接口时,Spring 选择 CGLib;
- Spring可以通过配置强制使用CGlib ,只需要配置
<aop:aspectj-autoproxy proxy-target-class="true"/>
修改proxyTargetClass