Java设计模式 | 设计模式内功之动态代理模式

写在前面: 代理模式,字面上的意思就是代理某个人去做某件事。比如代办证件,可以找代办公司帮忙代理办证。
根据代理的创建时期,代理模式分为静态代理和动态代理。

代理模式的应用场景

当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访问。使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。

动态代理

在程序运行时,运用反射机制动态创建而成。字节码随用随创建,随用随加载。 Spring的AOP中就使用了动态代理对代码的增强

应用案例: 文件服务对删除文件时增强。

实现如下:

1.抽象主题:

/**
* 抽象文件服务
*
* @Author JUNSHI
* @Create 2022-04-06 17:00
*/
public interface IFileService {
    
    /**
    * 删除文件
    */
    void deleteFile(String fileId);
    
}

2.真实主题:

/**
 * 对象存储上传文件
 *
 * @Author JUNSHI
 * @Create 2022-04-07 14:43
 */
@Service
public class OssFileService implements IFileService {


    @Override
    public void deleteFile(String fileId) {
        System.out.println("OSS删除文件:" + fileId);
    }
}

代理一: SpringBoot整合Jdk的动态代理实现(基于接口类的动态代理

/**
 * JDK代理服务
 * 基于接口类的动态代理
 *
 * @Author JUNSHI
 * @Create 2022-04-07 14:45
 */
@Service("proxyService")
public class ProxyService implements InvocationHandler{

    /**
     * 需要代理的目标对象
     */
    private Object target;

    /**
     * 作用:执行被代理对象的任何接口方法都会经过该方法
     * 方法参数的含义
     * @param proxy   代理对象的引用
     * @param method  当前执行的方法
     * @param args    当前执行方法所需的参数
     * @return 和被代理对象方法有相同的返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before执行~~~");
        // 反射机制
        Object invoke = method.invoke(target, args);
        System.out.println("After执行~~~");
        return invoke;
    }

    /**
     * 获取代理对象
     */
    public Object getProxy(Object targetObject){
        // 赋于真实对象
        this.target = targetObject;
        // 实现接口的类进行代理,代理真实对象
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
    }

}

代理二: SpringBoot整合Cglib的动态代理实现(基于子类的动态代理

/**
 * Cglib代理服务
 * 基于子类的动态代理
 *
 * @Author JUNSHI
 * @Create 2022-04-07 14:45
 */
@Service("cglibProxyService")
public class CglibProxyService implements MethodInterceptor {

    /**
     * 需要代理的真实对象
     */
    private Object target;

    /**
     * 获取代理对象
     */
    public Object getProxy(Object targetObject){
        // 赋于真实对象
        this.target = targetObject;
        // 实现接口的类进行代理,代理真实对象
        Enhancer enhancer = new Enhancer();
        // 用于指定被代理对象的字节码
        enhancer.setSuperclass(targetObject.getClass());
        // 设置回调
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }

    /**
     *
     * 执行北地阿里对象的任何方法都会经过该方法
     * @param proxy
     * @param method
     * @param args
     *    以上三个参数和基于接口的动态代理中invoke方法的参数是一样的
     * @param methodProxy :当前执行方法的代理对象
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Cglib-Before执行~~~");
        // 反射机制
        Object invoke = method.invoke(target, args);
        System.out.println("Cglib-After执行~~~");
        return invoke;
    }
}

测试用例:

@SpringBootTest
class SpringDesignModeApplicationTests {

    @Autowired
    private IFileService fileService;

    @Autowired
    private ProxyService proxyService;

    @Autowired
    private CglibProxyService cglibProxyService;


    @Test
    void testJDKProxyService() {
        IFileService proxy =(IFileService) proxyService.getProxy(fileService);
        // 真实对象删除文件
        fileService.deleteFile("2");

        System.out.println("================分隔符================");

        // 代理对象删除文件
        proxy.deleteFile("1");

    }

    @Test
    void testCglibProxyService() {
        IFileService proxy =(IFileService) cglibProxyService.getProxy(fileService);
        // 真实对象删除文件
        fileService.deleteFile("2");

        System.out.println("================分隔符================");

        // 代理对象删除文件
        proxy.deleteFile("1");

    }

}

1.JDK代理测试结果:

img
2. Cglib代理测试结果:
img


版权声明:本文为weixin_46146269原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。