代理模式 – 动态代理

代理模式 – 动态代理

 

目录

 动态代理

 例子-常规

代码:

问候 Greet

问候实现 GreetIml

商店 Shop

商店实现 ShopImpl

动态代理 DynamicProxy

测试:

结果:

分析

例子-优化

代码:

动态代理 ProxyDynamicSingle

测试:,

结果:

分析

总结:


 动态代理

 在代理模式中,使用的是静态代理的方式,那如何进行动态代理?

 

动态代理是什么?

   在程序运行时由Java反射机制动态生成。

 

如何实现呢?

     在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持

 

 例子-常规

 

代码:

问候 Greet

public interface Greet {
    void say(String name);
}

 

问候实现 GreetIml

public class GreetImpl implements Greet {
    @Override
    public void say(String name) {
        System.out.println("Hi! " + name);
    }
}

 

商店 Shop

public interface Shop {
    void sell(String wares);
}

 

商店实现 ShopImpl

public class ShopImpl implements Shop {
    @Override
    public void sell(String foodName) {
        System.out.println("sell the " + foodName);
    }
}

 

动态代理 DynamicProxy

public class DynamicProxy implements InvocationHandler {
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

在动态代理类中,实现InvocationHandler的接口,调用  method.invoke(target, args)

测试:

public class ProxyDynamicTest {
    public static void main(String[] args) {
        System.out.println("========== greet proxy ==========");
        Greet greet = new GreetImpl();
        DynamicProxy dynamicProxy = new DynamicProxy(greet);
        Greet greetProxy = (Greet) Proxy.newProxyInstance(greet.getClass().getClassLoader(),
                greet.getClass().getInterfaces(), dynamicProxy);
        greetProxy.say("lang");
        
        System.out.println("========== shop proxy ==========");
        Shop shop = new ShopImpl();
        dynamicProxy = new DynamicProxy(shop);
        Shop shopProxy = (Shop) Proxy.newProxyInstance(shop.getClass().getClassLoader(),
                shop.getClass().getInterfaces(), dynamicProxy);
        shopProxy.sell("coffe");
    }
}

 

结果:

========== greet proxy ==========

Before

Hi! lang

After

========== shop proxy ==========

Before

sell the coffe

After

 

分析

  在实现中,每次要Proxy.newProxyInstance(greet.getClass().getClassLoader(), greet.getClass().getInterfaces(), dynamicProxy); 不同的类都要那样处理,略显麻烦,可以进行优化下。该如何做的?
 

例子-优化

代码:

动态代理 ProxyDynamicSingle

public class ProxyDynamicSingle implements InvocationHandler {
    private Object target;

    public ProxyDynamicSingle(Object target) {
        this.target = target;
    }

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Before");
    }

    private void after() {
        System.out.println("After");
    }
}

 使用getProxy()的方式获取到代理类,在调动的时候就不用一一那个处理

测试:,

public class ProxyDynamicSingleTest {
    public static void main(String[] args) {
        System.out.println("========== greet proxy ==========");
        ProxyDynamicSingle proxyDynamicSingle = new ProxyDynamicSingle(new GreetImpl());
        Greet greetProxy = proxyDynamicSingle.getProxy();
        greetProxy.say("yan");

        System.out.println("========== shop proxy ==========");
        proxyDynamicSingle = new ProxyDynamicSingle(new ShopImpl());
        Shop shop = proxyDynamicSingle.getProxy();
        shop.sell("milk");
    }
}

 

结果:

========== greet proxy ==========

Before

Hi! yan

After

========== shop proxy ==========

Before

sell the milk

After

 

分析

  这样实现起来就简单多了。为什么代理类中有before,after的方法呢?联想到什么?spring的AOP实现,AOP的实现原理是基于动态代理

 

总结:

  动态代理对象不需要实现目标对象接口,但是目标对象一定要实现接口,否则不能使用动态代理,需要使用cglib代理。动态代理的应用使我们的类职责更加单一,复用性更强。

动态代理和cgli代理进行比较:

1,对象不同:

      Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);

      CGLIB能够代理普通类;

2,实现方式不同:

      Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;

      CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天狼1222

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值