代理模式

代理模式,静态、动态代理的实践

静态代理

静态代理实现步骤:

  1. 定义一个接口及其实现类;
  2. 创建一个代理类同样实现这个接口
  3. 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。

代码实现:

1、定义一个短信功能接口

public interface SmsService {
    String send(String message);
}

2、实现这个短信接口

public class SmsServiceImpl implements SmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}

3、创建代理类,并实现短信接口

public class SmsProxy implements SmsService {
	// 实际被代理对象
    private final SmsService smsService;

    public SmsProxy(SmsService smsService) {
        this.smsService = smsService;
    }

    @Override
    public String send(String message) {
        //调用方法之前,我们可以添加自己的操作
        System.out.println("before method send()");
        smsService.send(message);
        //调用方法之后,我们同样可以添加自己的操作
        System.out.println("after method send()");
        return null;
    }
}

4、使用

public class Main {
    public static void main(String[] args) {
        SmsService smsService = new SmsServiceImpl();
        SmsProxy smsProxy = new SmsProxy(smsService);
        smsProxy.send("java");
    }
}

动态代理

JDK 动态代理实现步骤

  1. 定义一个接口及其实现类;
  2. 自定义 InvocationHandler 并重写 invoke 方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑;
  3. 通过 Proxy.newProxyInstance (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象;

动态代理案例一

创建功能接口

public interface Human{
    void eat();

    void run();

    void walk();
}

创建被代理类,并实现功能类

class SuperMan implements Human{

    @Override
    public void eat(){
        System.out.println("超人不需要吃饭,需要太阳能!");
    }

    @Override
    public void run(){
        System.out.println("超人飞行速度为300km/h");
    }

    @Override
    public void walk(){
        System.out.println("超人的走路速度为90km/h");
    }
}

创建代理类并实现接口 InvocationHandler

重写里面的 invoke 方法

class MyInvocationHandler implements InvocationHandler{
    Object obj;

    // 实现被调用对象绑定
    public void bind(Object obj){
        this.obj = obj;
    }

    // 当通过代理类的对象,调用方法a时,就会自动调用如下方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{  //obj被代理类对象
        // 实现被代理类的方法调用逻辑
        // 该返回值作为当前类中的invoke()的返回值
        Object invoke = method.invoke(obj, args);
        return invoke;
    }
}

创建用于返回代理类对象的代理工厂

class ProxyFactory{
    // 创建一个静态方法 返回一个代理类对象
    public static Object getProxyInstance(Object obj){ //obj 被代理对象
        MyInvocationHandler handler = new MyInvocationHandler();
        // 进行绑定(绑定代理类和被代理对象)
        handler.bind(obj);
        // 通过类加载器获取被代理类的对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

测试

public class proxyTest{
    public static void main(String[] args){
        // 创建被代理类对象
        SuperMan superMan = new SuperMan();
        // 创建代理类对象--通过静态方法直接获取
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        // 通过代理类对象调用方法
        proxyInstance.eat();
        proxyInstance.run();
        proxyInstance.walk();
    }
}

代理模式

动态代理案例二

UserDAOImpl 实现 UserDAO 接口,UserDAOImpl 需要增加功能,使用代理对象的方法
利用 Proxy 代理类的静态方法 newProxyInstance() 创建被代理类的对象;
静态方法中的三个参数分别为: 类加载器、要实现功能修改的类的接口的数组(可以是多个接口)、 InvocationHandler 接口的实现类对象(匿名内部类、实现类对象)
在实现类或者匿名内部类中实现重写 invoke() 方法,在 invoke 方法中实现对功能的增强代码如下面的实现类中

定义一个功能接口

UserDao.java

public interface UserDAO {
    public abstract int add(int a,int b);
    public abstract String update(String id);
}

定义功能接口的实现类

UserDAOImpl.java

public class UserDAOImpl implements UserDAO{
    @Override
    public int add(int a, int b) {
        System.out.println("add() executing...");
        return a + b;
    }

    @Override
    public String update(String id) {
        System.out.println("update executing...");
        return id + ":update";
    }
}

创建代理对象类

public class MyProxy {
    public static void main(String[] args) {

        // 匿名实现类方式
        //        UserDAO userDAO = (UserDAO) Proxy.newProxyInstance(MyProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
        //            @Override
        //            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //                return null;
        //            }
        //        });

        Class [] interfaces = {UserDAO.class};
        UserDAOImpl userDAOImpl = new UserDAOImpl();

        UserDAO userDAO = (UserDAO) Proxy.newProxyInstance(MyProxy.class.getClassLoader(), interfaces, new UserDAOProxy(userDAOImpl));
        int result = userDAO.add(1, 2);
        System.out.println(result);
        System.out.println(userDAO.update("5"));
    }
}

// 创建代理类
class UserDAOProxy implements InvocationHandler {
    //利用有参构造的方式,对obj进行初始化(需要那个代理对象被创建,就把哪个对象传进来) 对应上边第三个参数
    private Object obj;

    public UserDAOProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在方法执行之前
        System.out.println("在需要更新的方法之前执行:  " + method.getName());

        //方法调用
        Object res = method.invoke(obj, args);

        //在方法执行之后
        System.out.println("在需要更新的方法之后:  ");
        return res;
    }
}

参考文章:

上一篇:Java的代理机制


下一篇:动态代理类理解