动态代理之JDK动态代理

       在了解JDK 动态代理之前先了解下动态代理,动态代理指的是程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象是由代理生成工具(如代理工厂类)在程序运行时由JVM根据反射等机制动态生成的。代理对象与目标对象的代理关系在运行时才确立。

        而静态代理是指程序在运行前就已经定义好了目标类的代理类。代理类与目标类的代理关系在程序运行之前就确立了。

----------------------------------------------------------分割线--------------------------------------------------------------

JDK动态代理:

通过 JDK 的 java.lang.reflect.Proxy 类实现动态代理,会使用其静态方法 newProxyInstance(),依据目标对象、业务接口以及增强逻辑三方,自动生成一个动态代理对象。

public static newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler)

loader: 目标类的类加载器,通过目标对象的反射可获取
interfaces: 目标类实现的接口数组,通过目标对象的反射可获取
handler: 业务增强逻辑,需要再定义

InvocationHandler 是个接口,具体介绍:

实现了InvocationHandler接口的类用于嘉庆目标类的主业务逻辑。此接口中有一个方法 invoke(),具体加强的代码逻辑就是定义在该方法中的。程序调用主业务逻辑是,会自动调用 invoke()方法。

invoke()方法介绍:

public Object invoke(Object proxy, Method method, Object[] args)

proxy: 代表生成的代理对象
method: 代表目标方法
args: 代表目标方法的参数

该方法是由代理对象自动调用的,所以这个三个参数值不用程序员给出。

第二个参数为Method 类对象,给类有一个方法也叫 invoke(), 可以调用目标类的目标方法。这俩个invoke()方法,虽然同名但是无关。

代理的实现:

(1)定义业务接口 IAccountService,其中含有抽象方法transfer()。

public interface IAccountService {
    // 主业务逻辑
    void transfer();
}

(2)定义目标类 AccountServiceImpl,该类实现了业务接口。在对接口方法的实现上,只实现主业务逻辑。该方法成为目标方法。

public class AccountServiceImpl implements IAccountService {

    /*
     * 目标方法
     */
    @Override
    public void transfer() {
        System.out.println("调用Dao层,完成转账主业务。");
    }
}

(3)定义主业务增强逻辑类MyExtension,该类需要实现接口invocationHandler。在该类中定义一个Object 类型的成员变量,还要定义一个带参的构造器,这个参数为 Object对象。目的是将目标对象引入该类,以便通过反射调用目标方法。

/*
 * 定义主业务增强逻辑
 */
public class MyExtension implements InvocationHandler {
    private Object target;

    public MyExtension() {
    }

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 增强主业务逻辑代码
        System.out.println("对转账用户进行身份验证");
        // 无论主业务方法有无参数,有无返回值,下面的写法均可兼顾
        return method.invoke(target, args);
    }
}

(4)定义客户类 Client,客户类中主要语句有三句:

         A:定义目标对象。在生成代理对象时会需要目标对象对其初始化。

         B:定义代理对象。代理类Proxy 会通过反射机制,自动实现IAccount接口。代理对象需要使用目标对象对其进行初始化。

         C:代理对象调用主业务方法。

public class MyTest {

    public static void main(String[] args) {

        // 定义目标对象
        IAccountService target = new AccountServiceImpl();
        // 创建代理对象,并使用目标对象初始化
        IAccountService service = (IAccountService) Proxy.newProxyInstance(
                        target.getClass().getClassLoader(), // 获取目标对象的类加载器
                        target.getClass().getInterfaces(),  // 获取目标类实现的所有接口
                        new MyExtension(target));           // 增强业务类
        // 此时执行的内容,就是对目标对象增加过的内容
        service.transfer();
    }

}

 

你可能感兴趣的:(设计模式,Java)