JavaSE-动态代理

1.1 动态代理

  • 动态代理的角色和静态代理的一样, 动态代理的代理类是动态生成的 . 静态代理的代理类是提前写好的。
  • 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理。
    • 基于接口的动态代理----JDK动态代理。
    • 基于类的动态代理–cglib。
    • 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist。

JDK的动态代理需要了解两个类 : InvocationHandler 和 Proxy

InvocationHandler【调用处理程序】

Object invoke(Object proxy, 方法 method, Object[] args)//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。 方法对象的声明类将是该方法声明的接
口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。 原始
类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean
。

Pxoxy【代理】

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

1.2 代码示例

Rent接口(抽象角色)

package cn.guardwhy.domain;
// 抽象角色:租房
public interface Rent {
    
    
    public void rent();
}

Landlord

package cn.guardwhy.domain;
// 真实角色: 房东,要出租房子
public class Landlord implements Rent {
    
    
    @Override
    public void rent() {
    
    
        System.out.println("房屋出租!!!");
    }
}

ProxyInvocationHandler 即代理角色

package cn.guardwhy.proxy;

import cn.guardwhy.domain.Rent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 该类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    
    
    // 1.被代理的接口
    private Rent rent;

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

    // 2.生成得到代理类

    public Object getProxy(){
    
    
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(), this);
    }

    // 3.处理代理实例,并且返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        seeHouse();
        // 动态代理的本质。就是使用反射机制实现
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }
    // 4.方法
    public void seeHouse(){
    
    
        System.out.println("带房客看房...");
    }
    // 收中介费
    public void fare(){
    
    
        System.out.println("收中介费");
    }
}

Client(租客)

package cn.guardwhy.client;

import cn.guardwhy.domain.Landlord;
import cn.guardwhy.domain.Rent;
import cn.guardwhy.proxy.ProxyInvocationHandler;

public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 1.真实角色
        Landlord landlord = new Landlord();
        // 2.代理角色
        ProxyInvocationHandler pith = new ProxyInvocationHandler();
        // 3.通过调用程序处理角色来处理要调用的接口对象
        pith.setRent(landlord);
        Rent proxy = (Rent) pith.getProxy();
        // 4.调用接口
        proxy.rent();
    }
}

执行结果

总结

一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口

1.3 深化动态代理

UserService

package cn.guardwhy.domain;
// 抽象角色,增删改查业务
public interface UserService {
    
    
    void add();
    void delete();
    void update();
    void query();
}

UserServiceImpl

package cn.guardwhy.domain;

// 真实对象,完成增删改查的操作
public class UserServiceImpl implements UserService {
    
    
    @Override
    public void add() {
    
    
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
    
    
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
    
    
        System.out.println("更新了一个用户");
    }

    @Override
    public void query() {
    
    
        System.out.println("查询一个用户");
    }
}

编写一个通用的动态代理实现的类!所有的代理对象设置为Object。

package cn.guardwhy.proxy;

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

public class ProxyInvocationHandler2 implements InvocationHandler {
    
    
    // 1.被代理的接口
    private Object target;
    // 2.set注入
    public void setTarget(Object target) {
    
    
        this.target = target;
    }

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

    // 4.处理代理实例,并且返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        // 调用方法
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    // 定义日志方法
    public void log(String msg){
    
    
        System.out.println("执行了" + msg + "方法" );
    }
}

Client(租客)

package cn.guardwhy.client;

import cn.guardwhy.domain.UserService;
import cn.guardwhy.domain.UserServiceImpl;
import cn.guardwhy.proxy.ProxyInvocationHandler2;

public class Client2 {
    
    
    public static void main(String[] args) {
    
    
        //1.真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //2.代理对象的调用处理程序
        ProxyInvocationHandler2 pith = new ProxyInvocationHandler2();
        //3.设置要代理的对象
        pith.setTarget(userService);
        // 动态生成代理类
        UserService proxy = (UserService) pith.getProxy();
        //4.调用方法
        proxy.add();
    }
}

执行结果

1.4 动态代理的好处

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

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

猜你喜欢

转载自blog.csdn.net/hxy1625309592/article/details/115080607