代理模式(Proxy Pattern)
核心作用
- 通过代理,控制对对象的访问。可以详细控制访问某个(类)对象的方法,在调用这个方法前走前置处理,调用方法后做后置处理(AOP的微观实现)
- AOP(Aspect Oriented Programming面向切面编程)的核心实现机制
核心角色
- 抽象角色
- 定义代理角色和真实角色的公开对外方法
- 抽象角色
- 实现抽象角色,定义真实角色所有实现的业务逻辑,供代理角色调用
- 关注真正的业务逻辑
- 代理角色
- 实现抽象角色,是真实角色的代理,可以通过真实角色的业务逻辑方法来实现抽象方法,并且可以附加子集的逻辑操作
- 将统一的流程控制放在代理角色中处理
应用场景
- 安全代理:屏蔽对真实角色的直接访问
- 远程代理:通过代理类处理远程方法调用
- 延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。
开发框架中应用场景
- structs2拦截器实现
- 数据库连接池关闭处理
- Hibernate中延时加载实现
- mybtais实现拦截器插件
- Aspect的实现
- Spring的AOP的实现
- 日志拦截
- 声明式事务处理
- web service
- …
分类
- 静态代理(静态定义代理类)
- 动态代理(动态生成代理类)
- JDK字典的动态代理
- javaassist字节码操作库实现
- CGLIB
- ASM(底层使用指令,可维护性较差)
静态代理
- 较简单 如下
动态代理
- 基于JDK实现(被代理类必须实现接口)
public interface Star{
sing();
dance();
}
//需要被代理的对象
public class TargetStar implements Star{
sing(){}
dance(){}
}
public class StarHandler implements InvocationHandler {
//构造器传入真实的TargetStar
Star star;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = method.invoke(star,args);
return invoke;
}
});
}
测试Client
public class Client{
main{
Star star = new TargetStar();
StarHandler handler= new StarHandler (star );
Star starproxy= (Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Star.class},handler)
}
starproxy.sing();
}
- 上面是分开写的比较细,简单写法中经常如下
public static void main(String[] args) {
Star targetStar = new TargetStar();
Star star = (Star) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), TargetStar.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("sing")) {
System.out.println("唱");
} else {
System.out.println("跳");
}
Object invoke = method.invoke(targetStar,args);
System.out.println(invoke);
return invoke;
}
});
star.sing();
star.dance();
}
或者使用lambda表达式简化写法
public static void main(String[] args) {
Star targetStar = new TargetStar();
Star star = (Star) Proxy.newProxyInstance(ProxyTest.class.getClassLoader(), TargetStar.class.getInterfaces(), (proxy, method, args1) -> {
if (method.getName().equals("sing")) {
System.out.println("唱");
} else {
System.out.println("跳");
}
Object invoke = method.invoke(targetStar, args1);
System.out.println(invoke);
return invoke;
});
star.sing();
star.dance();
}
- 基于CGLIB实现(不能被final修饰 ,基于字节码技术)
main {
Enhancer enhancer= new Enhancer();
Star star = (Star) enhancer.create(TargetStar.class, new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object invoke = methodProxy.invokeSuper(o, objects);
return invoke;
}
});
star.sing();
}
在结构上相似的装饰者模式比较
https://blog.csdn.net/mark_lq/article/details/48413485
https://www.cnblogs.com/ealenxie/p/9896269.html