zoukankan      html  css  js  c++  java
  • 动态代理两种实现方式

    今天又是周末,自己的春招也差不多结束了,百般无聊的状态下想写点东西。

    我想先提一个东西,比如你想要计算一段代码的执行时间,那么你之前肯定是这样写的。

    1 /**
    2  * 先定义一个接口
    3  * 
    4  * @author chang
    5  */
    6 public interface DoSomthing {
    7 
    8     void doSomthing() throws InterruptedException;
    9 }
     1 /**
     2  * 实现类
     3  * @author chang
     4  */
     5 public class DoSomthingImpl implements DoSomthing {
     6     
     7     @Override
     8     public void doSomthing() throws InterruptedException {
     9         Thread.sleep(100);
    10         System.out.println("这是主体的同容  " + System.currentTimeMillis());
    11         Thread.sleep(100);
    12     }
    13 }

    写死的方法,也是最笨的方法。

    在doSomthing前后加上before(), after()。这两个方法。 如果有其他方法想要执行befor,after,同样写死在代码里面。

    这就是所谓的静态代理,非常的麻烦以及代码十分的重复冗余,所以出现了伟大的动态代理。

    JDK动态代理:

     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 import java.lang.reflect.Proxy;
     4 
     5 public class JDKDynamicProxy implements InvocationHandler{
     6 
     7     Object o = null;
     8     
     9     public JDKDynamicProxy(Object o) {
    10         this.o = o;
    11     }
    12     
    13     public Object getProxy() {
    14         
    15         return Proxy.newProxyInstance(o.getClass().getClassLoader(), 
    16                 o.getClass().getInterfaces(), this);
    17     }
    18     
    19     @Override
    20     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    21         
    22         before();
    23         Object res = method.invoke(o, args);
    24         after();
    25         return res;
    26     }
    27     
    28     void before() {
    29         System.out.println(System.currentTimeMillis());
    30     }
    31     
    32     void after() {
    33         System.out.println(System.currentTimeMillis());
    34     }
    35     
    36 }
    1 public class Test {
    2     public static void main(String[] args) throws InterruptedException {
    3         
    4         JDKDynamicProxy jp = new JDKDynamicProxy(new DoSomthingImpl());
    5         DoSomthing ds = (DoSomthing) jp.getProxy();
    6         ds.doSomthing();
    7     }
    8 }

    会不会发觉扩展十分的方便。每次只用new一个动态代理类,并且把实现类的对象传过去,jdk就会自动的代理这个方法。

    每次你调用doSomthing方法的时候,自动执行before和after方法,非常的方便。

    但有个问题,JDK 给我们提供的动态代理只能代理接口,而不能代理没有接口的类。因为你的Proxy.newProxyInstance要传一个接口的参数过去,那又要怎么办呢?

    CGLib动态代理

     1 import java.lang.reflect.Method;
     2 import net.sf.cglib.proxy.Enhancer;
     3 import net.sf.cglib.proxy.MethodInterceptor;
     4 import net.sf.cglib.proxy.MethodProxy;
     5 
     6 public class CGLibDynamicProxy implements MethodInterceptor{
     7 
     8     public CGLibDynamicProxy() {}
     9     
    10     public <T> Object getProxy(Class<T> cls) {
    11         return Enhancer.create(cls, this);
    12     }
    13     
    14     @Override
    15     public Object intercept(Object target, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
    16         
    17         before();
    18         Object res = proxy.invokeSuper(target, arg2);
    19         after();
    20         return res;
    21     }
    22     
    23     void before() {
    24         System.out.println(System.currentTimeMillis());
    25     }
    26     
    27     void after() {
    28         System.out.println(System.currentTimeMillis());
    29     }
    30 }
    1 public class Test {
    2     public static void main(String[] args) throws InterruptedException {
    3         
    4         CGLibDynamicProxy cg = new CGLibDynamicProxy();
    5         DoSomthing ds = (DoSomthing) cg.getProxy(DoSomthingImpl.class);
    6         ds.doSomthing();
    7     }
    8 }

    同样new一个CGLibDynamicProxy对象,然后通过getProxy方法获得对象,然后直接调用方法即可。

    而Spring框架底层的AOP大概就是用这两种方法实现的。

  • 相关阅读:
    [C#]RichTextBox实现拖放
    [C#]WinForm动态删除控件 Controls.Remove()
    [C#]WinForm 中 comboBox控件之数据绑定
    [C#.Net]KeyDown(KeyUp)和KeyPress的区别
    [C#.NET]最简单的实现文本框的水印效果
    [C#.Net]对WinForm应用程序的App.config的使用及加密
    Spring MVC异常处理详解
    MAC与HMAC的介绍及其在AWS和Azure中的应用
    isDebugEnabled有什么用?
    在Mysql中Using filesort代表什么意思?
  • 原文地址:https://www.cnblogs.com/wenbochang/p/8899626.html
Copyright © 2011-2022 走看看