java JDK动态代理

JAVA学习网 2018-10-20 10:57:02

本篇随笔是对java动态代理中的JDK代理方式的具体实现。

首先需要定义一个接口,为其定义了两个方法:

public interface UserService {

     public void add();

     public void delete();
}

 

然后需要一个实现这个接口的实现类:
public class UserServiceImpl implements UserService {
     @Override
     public void add() {
   //添加一些操作
          System.out.println("UserServiceImpl中的add()方法被执行了");
     }
     @Override
     public void delete() {
     //添加一些操作
          System.out.println("UserServiceImpl中的delete()方法被执行了");
     }
}
 
此时如果要在调用add()方法和delete()方法时先输入一句话:System.out.println("动态代理开启");
第一种方式:直接在方法体内部输出,此时就会出现一个问题:“硬编码”,对以后的扩展不方便。
第二种方式:使用java中动态代理机制,主要有JDK和CGLIB两种方式。本文主要使用JDK的方式。
 
此时,创建一个动态代理类:
public class DynaProxyInvocationHandler implements InvocationHandler {
     // 定义被代理对象,该对象必须实现了至少一个接口
     private Object target;
     // 定义代理方法,该方法代理后的返回值类型是被代理对象原类型
     public Object Proxy(Object target) {
          this.target=target;
          return Proxy.newProxyInstance(
                   this.target.getClass().getClassLoader(),
                   this.target.getClass().getInterfaces(),
                   this);
     }
     /**
      * 当一个类实现了InvocationHandler接口后,必须实现invoke方法
      * 而这个方法就是增强被代理对象的方法
      */
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          System.out.println("动态代理开启");
          return method.invoke(this.target, args);
     }
}

 

其中的Proxy是JDK为我们提供的动态代理对象,该对象提供了newProxyInstance()来进行初始化,参数说明如下:
第一个参数:被代理对象的类装载器
第二个参数:被代理对象所实现的接口
第三个参数:实现InvocationHandler接口的类

而其中的invoke方法中有着三个参数:
第一个参数:代理对象,一般在动态代理中不会使用。
第二个参数:被代理对象所执行的方法
第三个参数:被代理对象所执行的方法的参数列表
 
此时,可以建立一个测试类查看一下效果:
public class DynaProxtTest {
     public static void main(String[] args) {
          // 创建被代理对象
          UserService userService = new UserServiceImpl();
          // 对象UserService进行代理
          UserService us = (UserService)new DynaProxyInvocationHandler().Proxy(userService);
          //调用代理后的方法
          us.add();
   System.out.println("=============");
          us.delete();
     }
}

 

此时控制台的输出会是:
动态代理开启
UserServiceImpl中的add()方法被执行了
=============
动态代理开启
UserServiceImpl中的delete()方法被执行了

 

此时,如果要对代理方法进行限制,可以使用以下方法:

     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          Object result = null;
          if(method.getName().contains("add")) {
              System.out.println("动态代理开启");
              result = method.invoke(this.target, args);
          }else {
              result = method.invoke(this.target, args);
          }
          return result;
     }

 

此时控制台的输出会是:
动态代理开启
UserServiceImpl中的add()方法被执行了
=============
UserServiceImpl中的delete()方法被执行了
 

 

因为Spring的AOP就是通过动态代理的机制实现的,所以还是需要好好的理解动态代理的机制的。

阅读(2309) 评论(0)