简介
为另一个对象提供代理,以便控制客户端对对象的访问。
使用场景
- 远程代理: 与远程对象交互;
- 虚拟代理:控制访问创建开销大的对象(先返回一个假引用);
- 保护代理:控制对原始对象的访问;
- 智能代理:当一个对象被引用时,提供一些额外的操作。
类图
角色说明:
ISubject
:抽象角色,声明了目标对象和代理对象的共同接口;RealSubject
:真实角色,真正处理请求的目标对象;Proxy
:代理角色,内部持有目标对象的引用,所以可以随时调用目标对象。
静态代理
示例
接口:
public interface HelloService {
void say(String message);
}
目标类:
public class HelloServiceImpl implements HelloService {
@Override
public void say(String message) {
System.out.println(message);
}
}
代理类:
public class HelloServiceProxy implements HelloService {
private HelloService helloService;
public HelloServiceProxy(HelloService helloService) {
this.helloService = helloService;
}
@Override
public void say(String message) {
System.out.println("代理开始------------");
helloService.say(message);
System.out.println("代理结束------------");
}
}
测试代码:
public static void main(String[] args) {
HelloService service = new HelloServiceProxy(new HelloServiceImpl());
service.say("hello");
}
输出结果:
代理开始------------
hello
代理结束------------
JDK动态代理
示例
接口:
public interface HelloService {
void say(String message);
}
目标类:
public class HelloServiceImpl implements HelloService {
@Override
public void say(String message) {
System.out.println(message);
}
}
代理:
public class JdkProxyService implements InvocationHandler {
private Object target;
public JdkProxyService(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始------------");
Object result = method.invoke(target, args);
System.out.println("代理结束------------");
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), this.target.getClass()
.getInterfaces(), this);
}
}
测试代码:
public static void main(String[] args) {
HelloService service = (HelloService) new JdkProxyService(new HelloServiceImpl()).getProxy();
service.say("hello");
System.out.println(service.getClass());
}
输出结果:
代理开始------------
hello
代理结束------------
class com.sun.proxy.$Proxy0
关键点有两处:
- 实现
InvocationHandler
接口,重写invoke
方法; - 用
Proxy
类的newProxyInstance
方法生成代理; - 目标对象需要实现了接口。
原理
相关类汇总
类 | 说明 |
---|---|
Proxy | Proxy |
InvocationHandler | |
WeakCache | WeakCache |
BiFunction | BiFunction |
Supplier | Supplier |
ProxyGenerator |
生成代理对象的逻辑在Proxy
类的newProxyInstance
方法中,newProxyInstance
主要源码如下(省略了部分代码):
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
final Class<?>[] intfs = interfaces.clone();
// 获取代理类的 Class对象
Class<?> cl = getProxyClass0(loader, intfs);
// 获取代理类的构造器
// constructorParams 是 Proxy 类的字段,值为数组: {InvocationHandler.class }
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 通过反射生成代理对象
return cons.newInstance(new Object[]{h});
}
getProxyClass0
源码如下:
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
从proxyClassCache
缓存中获取代理类。
proxyClassCache
是Proxy
类的字段,结构如下:
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new Proxy.KeyFactory(), new Proxy.ProxyClassFactory());
继续跟进WeakCache
类的get
方法,源码如下:
源码
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
if (factory == null) {
factory = new WeakCache.Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
get
方法入参:key
是类加载器,parameter
是代理接口集合;
WeakCache
类中有个字段map
,结构如下:
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();
可以把map
看成是个二级缓存:
- 第一级缓存的
key
为类加载器; - 第二级缓存的
key
为subKey
,通过subKeyFactory.apply(key, parameter)
可得到,所以是与代理接口集合关联的; - 第二级缓存的
value
为对应的代理;
主要流程:
- 以指定类加载器为
key
,去map
中查询第二级缓存; - 若找不到,则创建第二级缓存;
- 以
subKey
为key
,去第二级缓存查询; - 若找不到,则创建
Factory
类型(实现了Supplier<V>
接口)的对象supplier
,并放入缓存中; - 调用
supplier.get()
返回代理类。
其中Factory
类是WeakCache
的内部类。
继续跟进Factory
类的get
方法,源码如下:
源码
@Override
public synchronized V get() { // serialize access
// re-check
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try {
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue<V> cacheValue = new CacheValue<>(value);
// try replacing us with CacheValue (this should always succeed)
if (valuesMap.replace(subKey, this, cacheValue)) {
// put also in reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}
主要流程:
- 以
subKey
为key
,在第二级缓存valuesMap
中查询; - 通过
valueFactory.apply(key, parameter)
得到value
; - 将
value
封装成cacheValue
(CacheValue<V>
类型); - 用新值
cacheValue
覆盖第二级缓存中的旧值; - 最后返回
value
。
其中valueFactory
是WeakCache
类的字段,结构如下:
private final BiFunction<K, P, V> valueFactory;
值为new ProxyClassFactory()
;
ProxyClassFactory
类的apply
方法源码如下:
源码
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
apply
方法入参:key
是类加载器,parameter
是代理接口集合;
主要流程:
- 加载指定的所有的接口;
- 代理类名称拼接(
"com.sun.proxy.$Proxy" + num
),num
为递增的序号; - 生成字节码:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);
- 加载字节码并返回
Class
对象:defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length)
。
继续跟进ProxyGenerator
类的generateProxyClass
方法,源码如下:
源码
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
final byte[] var4 = var3.generateClassFile();
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}
Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
return var4;
}
主要是调用ProxyGenerator
的generateClassFile()
生成class
文件;
然后根据saveGeneratedFiles
参数确定是否对class
文件保存,saveGeneratedFiles
结构如下:
`private static final boolean saveGeneratedFiles =(Boolean)AccessController.doPrivileged(newGetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));`
默认情况下为false
,也就是不保存文件;为了方便了解原理,可以改下配置,如下:
public static void main(String[] args) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
HelloService service = (HelloService) new JdkProxyService(new HelloServiceImpl()).getProxy();
service.say("hello");
System.out.println(service.getClass());
}
可以看到在项目空间下自动生成了以下文件:
$Proxy0.class
内容如下:
源码
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import mncode.service.HelloService;
public final class $Proxy0 extends Proxy implements HelloService {
private static Method m1;
private static Method m2;
private static Method m3;
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 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 void say(String var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("mncode.service.HelloService").getMethod("say", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
说明:
- 继承了
Proxy
类,实现了HelloService
接口; - 有
4
个方法:equals
、hashCode
、toString
、say
; - 每个方法内部都会调用
InvocationHandler
对象的invoke
方法。
这里衔接之前自定义的invoke
方法:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始------------");
Object result = method.invoke(target, args);
System.out.println("代理结束------------");
return result;
}
应用
CGLIB动态代理
底层使用ASM
字节码生成技术来创建代理类,效率很高;目标类不需要实现接口,代理类继承目标类并重写方法;因为使用的继承的方式,所以目标类不能被final
修饰,否则报错;目标类中被final
或static
修饰的方法,不会被代理。
示例
public class ProductService {
public void create() {
System.out.println("创建商品");
}
}
public class CglibService implements MethodInterceptor {
private Object target;
public CglibService(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("代理开始------------");
Object result = proxy.invokeSuper(obj, args);
System.out.println("代理结束------------");
return result;
}
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
}
测试代码:
public static void main(String[] args) {
ProductService service = (ProductService) new CglibService(new ProductService()).getProxy();
service.create();
System.out.println(service.getClass());
}
输出结果:
代理开始------------
创建商品
代理结束------------
class mncode.service.ProductService$$EnhancerByCGLIB$$e184bf19
原理
查看生成的字节码文件,修改测试代码如下:
static {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\myProjects\\design-pattern");
}
public static void main(String[] args) {
ProductService service = (ProductService) new CglibService(new ProductService()).getProxy();
service.create();
System.out.println(service.getClass());
}
运行后,在E:\\myProjects\\design-pattern
路径下自动产生以下文件:
ProductService$$EnhancerByCGLIB$$e184bf19.class
内容如下:
源码
package mncode.service;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProductService$$EnhancerByCGLIB$$e184bf19 extends ProductService implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$create$0$Method;
private static final MethodProxy CGLIB$create$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("mncode.service.ProductService$$EnhancerByCGLIB$$e184bf19");
Class var1;
CGLIB$create$0$Method = ReflectUtils.findMethods(new String[]{"create", "()V"}, (var1 = Class.forName("mncode.service.ProductService")).getDeclaredMethods())[0];
CGLIB$create$0$Proxy = MethodProxy.create(var1, var0, "()V", "create", "CGLIB$create$0");
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
}
final void CGLIB$create$0() {
super.create();
}
public final void create() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$create$0$Method, CGLIB$emptyArgs, CGLIB$create$0$Proxy);
} else {
super.create();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 598313209:
if (var10000.equals("create()V")) {
return CGLIB$create$0$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public ProductService$$EnhancerByCGLIB$$e184bf19() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
ProductService$$EnhancerByCGLIB$$e184bf19 var1 = (ProductService$$EnhancerByCGLIB$$e184bf19)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (CGLIB$STATIC_CALLBACKS == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
ProductService$$EnhancerByCGLIB$$e184bf19 var10000 = new ProductService$$EnhancerByCGLIB$$e184bf19();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
ProductService$$EnhancerByCGLIB$$e184bf19 var10000 = new ProductService$$EnhancerByCGLIB$$e184bf19();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
ProductService$$EnhancerByCGLIB$$e184bf19 var10000 = new ProductService$$EnhancerByCGLIB$$e184bf19;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
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();
}
}
说明:
- 代理类继承了
ProductService
类,实现了Factory
接口; - 当调用代理对象的
create
方法时,会调用intercept
方法。
这里衔接之前自定义的intercept
方法:
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("代理开始------------");
Object result = proxy.invokeSuper(obj, args);
System.out.println("代理结束------------");
return result;
}
备注:
- 目标类不能被
final
修饰,否则会报错,Enhancer
类的generateClass
中有校检:
if (TypeUtils.isFinal(sc.getModifiers()))
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
- 目标类中被
final
或static
修饰的方法,不会被代理;
应用
扩展
1、CGlib动态代理中,如何通过代理对象去获取目标对象?
工具类:
public static Object getTargetObj(Object proxyObj) throws NoSuchFieldException, IllegalAccessException {
// 代理对象的字段CGLIB$CALLBACK_0(前面有源码)持有CglibService对象的引用
Field cglib = proxyObj.getClass().getDeclaredField("CGLIB$CALLBACK_0");
cglib.setAccessible(true);
// 反射获取CglibService对象
Object cglibService = cglib.get(proxyObj);
System.out.println("cglibService的类型:" + cglibService.getClass());
// CglibService对象的字段target持有目标对象的引用
Field target = cglibService.getClass().getDeclaredField("target");
target.setAccessible(true);
// 反射获取目标对象
Object targetObj = target.get(cglibService);
return targetObj;
}
测试代码:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
System.out.println("########代理对象测试########");
// 代理对象
ProductService proxyObj = (ProductService) new CglibService(new ProductService()).getProxy();
System.out.println("代理对象的类型:" + proxyObj.getClass());
// 调用代理对象
proxyObj.create();
System.out.println("########目标对象测试########");
// 目标对象
ProductService targetObj = (ProductService) getTargetObj(proxyObj);
System.out.println("目标对象的类型:" + targetObj.getClass());
// 调用目标对象
targetObj.create();
}
输出结果:
########代理对象测试########
代理对象的类型:class mncode.service.ProductService$$EnhancerByCGLIB$$e184bf19
代理开始------------
创建商品
代理结束------------
########目标对象测试########
cglibService的类型:class mncode.service.CglibService
目标对象的类型:class mncode.service.ProductService
创建商品
2、JDK动态代理中,如何通过代理对象去获取目标对象?
工具类:
public static Object getTargetObj(Object proxyObj) throws NoSuchFieldException, IllegalAccessException {
// 代理对象的字段h(在父类Proxy中)持有JdkProxyService对象的引用
Field h = proxyObj.getClass().getSuperclass().getDeclaredField("h");
h.setAccessible(true);
// 反射获取JdkProxyService对象
Object proxyService = h.get(proxyObj);
System.out.println("proxyService的类型:" + proxyService.getClass());
// HelloServiceProxy对象的字段target持有目标对象的引用
Field target = proxyService.getClass().getDeclaredField("target");
target.setAccessible(true);
// 反射获取目标对象
Object targetObj = target.get(proxyService);
return targetObj;
}
测试代码:
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
System.out.println("########代理对象测试########");
// 代理对象
HelloService proxyObj = (HelloService) new JdkProxyService(new HelloServiceImpl()).getProxy();
System.out.println("代理对象的类型:" + proxyObj.getClass());
// 调用代理对象
proxyObj.say("hello");
System.out.println("########目标对象测试########");
// 目标对象
HelloService targetObj = (HelloService) getTargetObj(proxyObj);
System.out.println("目标对象的类型:" + targetObj.getClass());
// 调用目标对象
targetObj.say("hello");
}
输出结果:
########代理对象测试########
代理对象的类型:class com.sun.proxy.$Proxy0
代理开始------------
hello
代理结束------------
########目标对象测试########
proxyService的类型:class mncode.service.JdkProxyService
目标对象的类型:class mncode.service.HelloServiceImpl
hello