设计模式之避免浪费_Proxy代理模式_必要时生成实例
前言
Github:https://github.com/HealerJean
1、Proxy代理模式
1.1、解释
Proxy
是代理人的意思,指的是代替别人进行工作,工作强度是有限的。当代理人无法完成的时候,就会去找本人去解决问题
代理提供的接口和原本的接口是一样的,代理模式的作用是不把实现直接暴露给client,而是通过代理这个层,代理能够做一些处理
使用场景 :在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 为其他对象提供一种代理对象以控制对这个对象的访问
1.2、示例代码
在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
1.2.1、买房子接口
public interface BuyHouse {
void buyHosue();
}
1.2.1.1、买房子实现类
public class BuyHouseImpl implements BuyHouse {
@Override
public void buyHosue() {
System.out.println("我要买房");
}
}
1.2.2、静态代理
1.2.2.1、BuyHouseProxy
实现 BuyHouse
会发现是委托模式,有点像适配器和装饰器吧
public class BuyHouseProxy implements BuyHouse {
private BuyHouse buyHouse;
public BuyHouseProxy(BuyHouse buyHouse) {
this.buyHouse = buyHouse;
}
@Override
public void buyHosue() {
buyHouse.buyHosue();
}
}
1.2.3、测试
public class ProxyTest {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouseImpl();
buyHouse.buyHosue();
BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
buyHouseProxy.buyHosue();
}
}
1.3、jdk
动态代理
1.3.1、jdk
动态代理控制器
public class DynamicProxyHandler implements InvocationHandler {
private Object object;
public DynamicProxyHandler(final Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
1.3.2、测试
public class DynamicProxyTest {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouseImpl();
System.out.println("buyHouse " + buyHouse.getClass().getName());
DynamicProxyHandler handler = new DynamicProxyHandler(buyHouse);
// 1、第一个参数 指定当前目标对象使用的类加载器
// 2、第二个参数 指定目标对象实现的接口的类型 接口列表
// 3、第三个参数 指定动态处理器,
BuyHouse proxyBuyHouse = (BuyHouse)
Proxy.newProxyInstance(BuyHouse.class.getClassLoader(),
buyHouse.getClass().getInterfaces(),
handler);
System.out.println("proxyBuyHouse :" + proxyBuyHouse.getClass().getName());
proxyBuyHouse.buyHosue();
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", buyHouse.getClass().getInterfaces());
String code = IOUtils.toString(bytes, "utf-8");
FileOutputStream fileOutputStream = new FileOutputStream("D:/study/HealerJean.github.io/_posts/1_设计模式/hlj-design-pattern/porxy.class");
IOUtils.write(bytes, fileOutputStream);
}
}
1.3.3、$Proxy0
代理类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import com.hlj.moudle.design.D09避免浪费.D21Proxy代理模式.BuyHouse;
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 BuyHouse {
private static Method m1;
private static Method m2;
private static Method m4;
private static Method m0;
private static Method m3;
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 int countAdd(int var1) throws {
try {
return (Integer)super.h.invoke(this, m4, 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);
}
}
public final void buyHosue() throws {
try {
super.h.invoke(this, m3, (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");
m4 = Class.forName("com.hlj.moudle.design.D09避免浪费.D21Proxy代理模式.BuyHouse").getMethod("countAdd", Integer.TYPE);
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m3 = Class.forName("com.hlj.moudle.design.D09避免浪费.D21Proxy代理模式.BuyHouse").getMethod("buyHosue");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
1.3.3.1、源码解析
// 1、第一个参数 指定当前目标对象使用的类加载器
// 2、第二个参数 指定目标对象实现的接口的类型 接口列表
// 3、第三个参数 指定动态处理器,
BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(
BuyHouse.class.getClassLoader(),
buyHouse.getClass().getInterfaces(),
handler);
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
/** parameter types of a proxy class constructor */
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
protected InvocationHandler h;
private Proxy() {
}
// 传入代理处理器,也就是我们自定义的那个 DynamicProxyHandler
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
}
@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);
}
//获取通过接口生成 $Proxy0 代理类
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取有参构造器 参数为 InvocationHandler.class (我们这是 DynamicProxyHandler )
final Constructor<?> cons = cl.getConstructor(constructorParams);
// h -》 DynamicProxyHandler对象
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);
}
}
1.3、CGLIB
动态代理
1.3.1、动态代理类
public class CglibProxy implements MethodInterceptor {
@SuppressWarnings("unchecked")
public <T> T getInstance(Object target, Class<T> clazz) {
//字节码加强器:用来创建动态代理类
Enhancer enhancer = new Enhancer();
//代理的目标对象
enhancer.setSuperclass(target.getClass());
//回调类,在代理类方法调用时会回调Callback类的intercept方法
enhancer.setCallback(this);
//创建代理类
Object result = enhancer.create();
return (T)result;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//调用目标类(父类)的方法
Object result = proxy.invokeSuper(obj, args);
return result;
}
}
1.3.2、测试
public class CglibProxyTest {
public static void main(String[] args){
BuyHouseImpl buyHouse = new BuyHouseImpl();
CglibProxy cglibProxy = new CglibProxy();
BuyHouseImpl buyHouseCglibProxy =cglibProxy.getInstance(
buyHouse,
BuyHouseImpl.class);
buyHouseCglibProxy.buyHosue();
}
}