需求场景
我们引用了开源jar包,需要扩展。我们又不能直接改jar包,违反了开闭原则。通常我们使用代理模式,在中间加一层。软件行业有句话:”如果解决不了,就加一层“。
静态代理
步骤
- 第三方jar包中的目标类(即被代理类);
- 我们创建一个代理类,和目标类实现同样的接口,在内部调用目标类。
- 在代码中使用。
/**
* 第三方jar包中的:目标类接口
*
* @author lsh by 2020/4/29
*/
public interface DoSthService {
void doSth();
}
/**
* 第三方jar包中的:目标类实现类
*
* @author lsh by 2020/4/29
*/
public class DoSthServiceImpl implements DoSthService {
@Override
public void doSth() {
System.out.println("被代理类 do sth");
}
}
/**
* 静态代理类
*
* @author lsh by 2020/4/29
*/
public class DoSthServiceImplProxy implements DoSthService {
@Override
public void doSth() {
// 加前置逻辑
System.out.println("before...");
// 委托给被代理类执行
// 这里也可以构造器注入
DoSthService service = new DoSthServiceImpl();
service.doSth();
// 加后置逻辑
System.out.println("after...");
}
}
// 代码中直接使用代理类即可
DoSthServiceImplProxy proxy = new DoSthServiceImplProxy();
proxy.doSth();
缺点
如果这个接口有很多方法,每个方法都要重写,很麻烦。
动态代理
JDK动态代理
步骤
- 创建一个实现了InvocationHandler接口的类,这个类中写清楚前后处理逻辑;
- 业务代码中用
Proxy.newProxyInstance
方法创建代理类;
/**
* 增强类:只有增强逻辑,没有任何目标类相关信息,完全解耦
*
* @author lsh by 2020/4/29
*/
public class JDKDynamicProxyEnhance implements InvocationHandler {
/**
* 这是一个Object类,只有运行时才知道传入的具体目标类
*/
private Object object;
public JDKDynamicProxyEnhance(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("jdk proxy...before...");
// 编写代码时,这里无需知道被代理的方法名,运行时动态传入
Object invoke = method.invoke(object, args);
System.out.println("jdk proxy...after...");
return invoke;
}
}
// 业务代码中需要三个参数:
// 1.创建第三方jar包中目标类的对象,这里可以是任何类的对象
// 2. 根据这个对象创建实现了InvocationHandler接口的增强类,
DoSthService service = new DoSthServiceImpl();
JDKDynamicProxyEnhance enhance = new JDKDynamicProxyEnhance(service);
DoSthService proxy = (DoSthService) Proxy.newProxyInstance(service.getClass().getClassLoader(), new Class[]{DoSthService.class},
enhance);
// 3. 业务中使用
proxy.doSth();
总结
从上面的代码中可以看到,动态代理定义增强类的时候,无需知道这个增强器是增强哪个类。就像我们生产了一个发动机,但是不知道以后会用在什么车上一样。只有用到的时候才会组装成整体。这里也是一样,只有用到的时候才告诉增强器要增强的类,然后用Proxy.newProxyInstance
组装焊接成一个整体Proxy。
来源:oschina
链接:https://my.oschina.net/qingjing/blog/4258519