Java常见代理proxy

静态代理

public interface Hello {
    public void say();
}
public class HelloImpl implements  Hello{
    public void say() {
        System.out.println("hello");
    }
}

现在想在hello前后做些事:使用代理

public class HelloProxy {
    private Hello hello;
    public HelloProxy(){
        hello=new HelloImpl();
    }
    public void say(){
        before();
        hello.say();
        after();
    }
    private void after() {
        System.out.println("before");
    }
    private void before() {
        System.out.println("after");
    }
}

结果:
在这里插入图片描述

但是我们不能对每个想要的能力都单独写一个代理,于是就有了动态代理

动态代理

public class DynamicProxy implements InvocationHandler{
    private Object target;
    public DynamicProxy(Hello hello){
        target=hello;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result=method.invoke(target,args);
        after();
        return result;
    }
    private void after() {
        System.out.println("before");
    }
    private void before() {
        System.out.println("after");
    }
}

DynamicProxy实现了 InvocationHandler, InvocationHandler有一个反射方法invoke()必须实现。

下面是使用方法:

Hello hello=new HelloImpl();

DynamicProxy dynamicProxy=new DynamicProxy(hello);

Hello helloProxy= (Hello) Proxy.newProxyInstance(
hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
dynamicProxy);

helloProxy.say();

意思就是通过DynamicProxy去包装了一个HelloImpl的实例,然后调用JDK给我们提供的Proxy的newProxyInstance()方法去动态创建一个Hello接口的代理类
传进去的参数依次为:被代理的类的类加载器,被代理的类的实现接口列表,动态代理对象

通过封装可以更加简洁:

....
public <T> T getProxy(){
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
....
Hello hello=new HelloImpl();

DynamicProxy dynamicProxy=new DynamicProxy(hello);

Hello helloProxy=dynamicProxy.getProxy();

helloProxy.say();

但是如果我们需要代理的类没有实现的接口,上面方法就不适用了,为此找到了CGLIB

CGLIB动态代理

这是一个在运行期间动态生成字节码的类,也就是动态生成代理类

public class CGLIBProxy implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        before();
        Object result=proxy.invokeSuper(obj,args);
        after();
        return result;
    }
    public <T> T getProxy(Class<T> cls){
        return (T) Enhancer.create(cls,this);
    }
    private void after() {
        System.out.println("before");
    }
    private void before() {
        System.out.println("after");
    }
}

其中的Enhancer.create()方法的流程是:
Cglib根据父类,Callback, Filter 及一些相关信息生成key.
然后根据key 生成对应的子类的二进制表现形式
使用ClassLoader装载对应的二进制,生成Class对象,并缓存
最后实例化Class对象,并缓存

再通过下面代码进行调用:

CGLIBProxy cglibProxy=new CGLIBProxy();
        Hello helloProxy=cglibProxy.getProxy(HelloImpl.class);
        helloProxy.say();

改成单例模式将会更加简单

public class CGLibProxySig implements MethodInterceptor {
    private static CGLibProxySig instance=new CGLibProxySig();
    private CGLibProxySig(){
    }
    public static CGLibProxySig getInstance(){
        return instance;
    }
    public <T> T getProxy(Class<T> cls){
        return (T) Enhancer.create(cls,this);
    }
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        before();
        Object result=proxy.invokeSuper(obj,args);
        after();
        return result;
    }
    private void after() {
        System.out.println("before");
    }
    private void before() {
        System.out.println("after");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值