从今天开始更新java设计模式相关的东西,之前虽然也对java设计模式有过学习单都是走马观花或者应付面试.现在工作中遇到了挑战,编写出优雅的代码成为非常迫切的事情;
代理模式
代理模式是java中常用的设计模式,在比如说在spring中的事物管理就是使用的代理模式;
1.为什么要使用代理模式
所有的设计模式都具有一个目标: 提高代码的复用率,这一点非常重要;
代理模式可以抽取通用的代码生成代理类,通过代理类执行目标对象的方法实现了代码的复用,经典的案列:spring的AOP;
2.代理模式的分类
- 静态代理
- 动态代理
- java动态代理
- cglib动态代理
2.1静态代理
静态代理非常简单,代理类持有目标类的对象,在执行目标方法的时候可以进行一些自定义的操作
public class UserDaoProxy implements IUserDao{
private IUserDao target;
public UserDaoProxy(IUserDao target){
this.target = target;
}
@Override
public CansResult save() {
// 记录日志
System.out.println("记录日志--------------");
CansResult res = target.save();
System.out.println("打印返回值:" + res);
return res;
}
}
2.2 动态代理
静态代理属于硬编码在工作中应用场景不多一般只用来学习方便理解,动态代理才是我们工作中常接触到的,动态代理可以在程序执行过程中动态生成代理类,在执行目标方法之前之后执行我们想要的操作,比如记录日志,权限校验等等;
java动态代理
java动态代理有一个缺点: 需要实现接口,如果没有实现接口则不能使用java的动态代理但是可以使用cglib动态代理
public class ProxyFactory {
/**
* 目标对象
*/
private Object target;
public ProxyFactory(Object target){
this.target = target;
}
/**
* 给目标对象生成代理
* @return
*/
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(Object proxy, Method method, Object[] args) -> {
System.out.println("开始事务2");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事务2");
return returnValue;
});
}
}
/**
* 使用java动态代理
* 需要接口
*/
@Test
public void javaDynamicProxy() {
IUserDao proxy = (IUserDao) new ProxyFactory(userDao).getProxyInstance();
proxy.save();
}
cglib动态代理
cglib动态代理应用广泛,因为没有java动态代理必须实现接口的限制,并且据说效率也更高
public class CglibProxyFactory implements MethodInterceptor {
/**
* 维护目标对象
*/
private Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
/**
* 给目标创建一个代理对象
*
* @return
*/
public Object getProxyInstance() {
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始事务");
// 执行目标对象方法
Object invoke = method.invoke(target, objects);
System.out.println("提交事物");
return invoke;
}
}
/**
* Cglib 代理
* 并没有实现接口
*/
@Test
public void cglibDynamicProxy() {
// 代理对象
UserDaoImpl proxyInstance = (UserDaoImpl) new CglibProxyFactory(userDao).getProxyInstance();
// 执行方法
proxyInstance.save();
}