动态代理模式

动态代理

1、动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口---JDK动态代理
    • 基于类:cglib
    • java字节码实现:JAVAssist

我们这里使用JDK的原生代码来实现,其余的道理都是一样的!

JDK的动态代理需要了解两个类

核心:InvocationHandlerProxy,打开JDK帮助文档看看

【InvocationHandler:调用处理程序】

  • 每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
 public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;

// 参数解释:
// proxy -- 代理角色
// method -- 代理角色调用的方法
// args -- 代理角色调用的方法传递的参数

【Proxy : 代理】

  • Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

  • 为某个接口创建代理实例

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
    
// 参数解释:
// loader -- 类加载器
// interfaces -- 代理类实现的接口列表
// h -- 调用处理程序

代码实现

抽象角色和真实角色和之前的一样!

1、Rent . java 即抽象角色

package com.edgar.demo03;

// 抽象角色:租房
public interface Rent {
    void rent();
}

2、LangLord. java 即真实角色

package com.edgar.demo03;


//真实角色: 房东,房东要出租房子
public class LangLord implements Rent {


    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

3、ProxyInvocationHandler. java 即代理角色

package com.edgar.demo03;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 等会我们会用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {

    // 被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    // 生成得到代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),
               this.rent.getClass().getInterfaces(),this);
    }

    // 处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制实现!
        this.seeHouse();
        Object result = method.invoke(this.rent, args);
        this.fare();
        return result;
    }

    public void seeHouse(){
        System.out.println("中介带看房子");
    }

    public void fare(){
        System.out.println("收中介费");
    }
}

4、Client . java

package com.edgar.demo03;

public class Client {

    public static void main(String[] args) {
        // 真实角色
        LangLord langLord = new LangLord();
        // 代理实例的调用程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        // 将真实角色放置进去
        pih.setRent(langLord);
        // 动态生成对应的代理类!
        Rent proxy = (Rent) pih.getProxy(); 
        proxy.rent();

}

核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个实现类,代理的是接口!

2、动态代理再理解

我们来使用动态代理实现代理我们之前写的UserService!

我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!

package com.edgar.demo03;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 等会我们会用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {

    // 被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    // 生成得到代理类
    public Object getProxy(){
       return Proxy.newProxyInstance(this.getClass().getClassLoader(),
               this.target.getClass().getInterfaces(),this);
    }

    // 处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制实现!
        this.log(method.getName());
        Object result = method.invoke(this.target, args);
        return result;
    }

    public void log(String methodName){
        System.out.println("执行了"+methodName+"方法");
    }
}

测试!

package com.edgar.demo03;

import com.edgar.demo02.UserService;
import com.edgar.demo02.UserServiceImpl;

public class Client {

    public static void main(String[] args) {
        // 真实角色
        UserService userService = new UserServiceImpl();
        // 代理实例的调用程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        // 将真实角色放置进去
        pih.setTarget(userService);
        // 动态生成代理类
        UserService proxy = (UserService) pih.getProxy();
        proxy.delete();
    }
}

测试,增删改查,查看结果!

动态代理的好处

静态代理有的它都有,静态代理没有的,它也有!

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
  • 公共的业务由代理来完成 . 实现了业务的分工 ,
  • 公共业务发生扩展时变得更加集中和方便 .
  • 一个动态代理 , 一般代理某一类业务
  • 一个动态代理可以代理多个实现类,代理的是接口!

动态代理模式

上一篇:EmmyLua 注解标记总结


下一篇:过滤器