静态代理

  1. 抽象接口
  2. 目标类和代理类实现同一个抽象接口
  3. 在代理类中通过构造方法将目标类注入
  4. 通过操作代理类的方式 来实现对目标类业务的操作
/**
 *  目标类和代理类都要实现抽象接口的抽象方法
 */
public interface StudentMapper {

    public void delete();
}


/**
 * 目标对象 实现抽象接口 执行删除
 */
public class StudentImpl implements StudentMapper {

    @Override
    public void delete() {
        System.out.println("目标类删除");
    }
}

/**
 * 代理对象 实现抽象接口 执行删除
 */
public class StudentProxyImpl implements StudentMapper {

    private StudentImpl studentImpl;

    public StudentProxyImpl(StudentImpl studentImpl) {
        this.studentImpl = studentImpl;
    }

    public void setStudentImpl(StudentImpl studentImpl) {
        this.studentImpl = studentImpl;
    }

    public StudentProxyImpl() {
    }

    @Override
    public void delete() {
        studentImpl.delete();
    }
}


    public static void main(String[] args) {

        StudentImpl student = new StudentImpl();
        // 构造方法注入对象
        StudentProxyImpl studentProxy1 = new StudentProxyImpl(student);
        studentProxy1.delete();
        // spring中建议用set方法注入对象
        StudentProxyImpl studentProxy2 = new StudentProxyImpl();
        studentProxy2.setStudentImpl(student);
        studentProxy2.delete();
    }

优点:

  1. 代理类可以继续去做别的操作,而目标类不会受到干扰。

缺点:

  1. 每新增一个目标类对应的就会多出一个代理类
  2. 共同实现的接口如果新增方法,那么代理类和目标类都要维护

JDK动态代理

Java语言中位于java.lang.reflect包下的编程机制,通InvocationHandler接口和Proxy类实现。

  1. 定义一个接口
  2. 目标类实现这个接口
  3. 编写一个动态代理类实现InvocationHandler接口,重写invoke()方法
  4. 引用目标类并通过set方法注入目标类
  5. 动态代理类的静态方法newInstance方法,通过反射机制创建一个新的接口实现类(代理类)https://blog.csdn.net/qq_34534731/article/details/150521441?spm=1011.2415.3001.5331
  6. 代理调用方法,达到目标类执行的效果
package com.cht.mapper;

public interface StudentMapper {

    public abstract void delete();
}



public class StudentImpl implements StudentMapper {
    @Override
    public void delete() {
        System.out.println("目标类删除");
    }
}




public class DynamicsProxy implements InvocationHandler {

    // 目标类
    private StudentImpl studentImpl;

    // 通过set方法注入目标类
    public void setStudentImpl(StudentImpl studentImpl) {
        this.studentImpl = studentImpl;
    }

    // 通过目标类的接口获取它的代理类,代理类其实就是接口的另一个实现类,只是通过动态代理反向获取。
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), studentImpl.getClass().getInterfaces(), this);
    }

    // 通过反射机制,拦截代理类的方法调用。并可以添加自己的其它功能
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("日志开始");
        // 拦截代理类的方法调用
        Object invoke = method.invoke(studentImpl, args);
        System.out.println("日志结束");
        return invoke;
    }

}



    public static void main(String[] args) {

        // 目标类
        StudentImpl studentImpl = new StudentImpl();
        // 动态代理注入目标类
        DynamicsProxy dynamicsProxy = new DynamicsProxy();
        dynamicsProxy.setStudentImpl(studentImpl);
        // 通过目标类获取它接口对应的理类
        StudentMapper proxy = (StudentMapper) dynamicsProxy.getProxy();
        proxy.delete();
    }
    // 目标类
    private Object target;

    // 通过set方法注入目标类
    public void setTarget(Object target) {
        this.target = target;
    }

优点:

  1. 一个接口可以通过反射创建多个代理类
  2. 进需要维护目标类,而代理类是反射动态生成的不需要单独再去维护
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐