代理模式

11、代理

场景:

1、租房:包括房东(真实对象),中介(代理对象),客户(被代理对象)

  • 房东:想要租房,只想租房,不想管带看房、签合同等操作。

    • 租房接口:里面包含租房方法【因为不可能只有你一个人要租房】
    • 房东类:里面实现了租房接口
  • 中介:此时出现了中介,中介帮房东租房,包括带看房、签合同、以及获取自己的中间费用

    • 中介类:同样实现租房接口,但是里面实现的方法是set房东类完成的,其他操作中介类自行添加
  • 客户:客户不用去找房东,直接找中介,中介带你做你所需要的任何操作。

    • 客户类:只需要new 中介类,就可以完成租房或者其他一系列操作

静态代理

实例测试静态代理模式

Why?

  • UserDaoImpl实现了UserDao接口;
  • 现有新的需求,要在每个实现的方法前添加日志
  • 一般不能修改原有的代码,所以使用一个代理类,将所需要的一些代码切入进去
  • 用户访问的时候,就直接访问代理类
  • 代理类同样需要实现接口

UserDao

public interface UserDao {

    //增
    int add();

    //删
    int delete();

    //查
    List<User> select();

    //改
    int update();

}

UserDaoImpl

public class UserDaoImpl implements UserDao {
    @Override
    public int add() {
        System.out.println("增");
        return 0;
    }

    @Override
    public int delete() {
        System.out.println("删");
        return 0;
    }

    @Override
    public List<User> select() {
        System.out.println("查");
        return null;
    }

    @Override
    public int update() {
        System.out.println("改");
        return 0;
    }
}

StaticProxy

public class StaticProxy implements UserDao {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public int add() {
        log("正在执行增加操作");
        userDao.add();
        return 0;
    }

    @Override
    public int delete() {
        log("正在执行删除操作");
        userDao.delete();
        return 0;
    }

    @Override
    public List<User> select() {
        log("正在执行查询操作");
        userDao.select();
        return null;
    }

    @Override
    public int update() {
        log("正在执行修改操作");
        userDao.update();
        return 0;
    }

    //需求:切入一段日志
    private static void log(String msg){
        System.out.println("[DEBUG]"+msg);
    }

    public void myMethod(){
        System.out.println("这是我代理类特有的方法");
    }
}

Test

@Test
public void test(){
    //真实对象需要做的事情
    UserDao userDao = new UserDaoImpl();

    //需要一个代理对象
    StaticProxy proxy = new StaticProxy();

    //代理对象去代理真实类【set方法】
    proxy.setUserDao(userDao);

    //执行被代理对象需要执行的操作
    proxy.add();

    //代理对象还可以自己做一些额外的操作
    proxy.myMethod();
}

好处:

不用修改自身原来的代码而动态实现代码的切入;

真实对象只需负责主要的业务,不用关心一些公共的业务,实现的业务的分工。

坏处:

静态代理一个真实对象就会产生一个代理对象,代码量增加,效率变低。

动态代理

动态代理的方式:

  1. 基于接口:JDK动态代理
  2. 基于类:cglib
  3. java字节码:javassist

动态代理需要了解2个类:

  • Proxy:生成代理对象
  • InvocationHandler:代理对象处理程序
    • 实现该类,来创建代理对象和通过反射机制执行代理对象所要执行的操作

DynamicProxy

/**
 * 动态代理的实现
 */
//用来创建代理对象,并执行代理程序
public class DynamicProxy implements InvocationHandler {

    //代理类所需要代理的真实对象
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    //获取代理对象
    public Object getProxy(){
        /**
         * 参数一:生成代理对象的类加载器
         * 参数二:代理类所要代理的接口
         * 参数三:指实现InvocationHandler的类
         */
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
    }


    //代理对象处理方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //使用代理类method去执行,参数一指的就是所需要代理的真实对象
        Object invoke = method.invoke(object, args);
        return invoke;
    }
}

Test

@Test
public void test1(){
    //真实对象所需要执行的操作
    UserDao user = new UserDaoImpl();

    //创建代理对象处理程序
    DynamicProxy proxy = new DynamicProxy();

    //设置所要代理的真实对象
    proxy.setObject(user);

    //创建代理对象
    UserDao proxy1 = (UserDao) proxy.getProxy();

    //执行
    proxy1.add();

}

总结:静态代理和动态代理的区别?

静态代理:

​ 一个类只能创建一个代理对象;

​ 代理对象需要程序员自己手动创建;

动态代理

​ 可研通过JDK原生接口,或者cglib包动态为所有类创建代理对象;

​ 是动态创建的,不用自己手动创建;

posted @ 2020-08-14 23:04  itch  阅读(171)  评论(0编辑  收藏  举报