给某一个对象提供一个代理,并由代理对象控制对原对象的引用
目标对象/被代理对象 ------ 房主:真正的租房的方法
代理对象 ------- 黑中介:有租房子的方法(调用房主的租房的方法)
执行代理对象方法的对象 ---- 租房的人
流程:我们要租房----->中介(租房的方法)------>房主(租房的方法)
抽象:调用对象----->代理对象------>目标对象
优点
- 代理模式能将代理对象与正式被调用的目标对象分离
- 一定程度上降低了系统的耦合度,扩展性好
- 保护目标对象
- 增强目标对象
缺点
- 代理模式会造成系统设计中类的数目增加
- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
- 增加系统的复杂度
静态代理

接口
public interface HelloInterface {
void sayHello();
}
被代理类
public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("Hello zhanghao!");
}}
代理类
public class HelloProxy implements HelloInterface{
private HelloInterface helloInterface = new Hello();
@Override
public void sayHello() {
System.out.println("Before invoke sayHello" );
helloInterface.sayHello();
System.out.println("After invoke sayHello");
}}
调用
public static void main(String[] args) {
HelloProxy helloProxy = new HelloProxy();
helloProxy.sayHello();
}
输出:
Before invoke sayHello
Hello zhanghao!
After invoke sayHello
动态代理
- 不用手动编写一个代理对象,不需要一一编写与目标对象相同的方法,这个过程,在运行时 的内存中动态生成代理对象
- 字节码随用随创建,随用随加载
- 对方法做一些增强
基于接口的动态代理
提供者:JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。
public interface IOrderDao {
int insert(Order order);
}
public class OrderDaoImpl implements IOrderDao {
@Override
public int insert(Order order) {
System.out.println("Dao层添加Order成功");
return 1;
}
}
public interface IOrderService {
int saveOrder(Order order);
}
public class OrderServiceImpl implements IOrderService {
private IOrderDao iOrderDao;
@Override
public int saveOrder(Order order) {
iOrderDao = new OrderDaoImpl();
System.out.println("Service层调用Dao层添加Order");
return iOrderDao.insert(order);
}
}
代理类
public class OrderServiceDynamicProxy implements InvocationHandler {
private Object target;
public OrderServiceDynamicProxy(Object target) {
this.target = target;
}
public Object bind(){
Class cls = target.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object argObject = args[0];
beforeMethod(argObject);
Object object = method.invoke(target,args);
afterMethod();
return object;
}
private void beforeMethod(Object obj){
int userId = 0;
System.out.println("动态代理 before code");
if(obj instanceof Order){
Order order = (Order)obj;
userId = order.getUserId();
}
int dbRouter = userId % 2;
System.out.println("动态代理分配到【db"+dbRouter+"】处理数据");
//todo 设置dataSource;
DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
}
private void afterMethod(){
System.out.println("动态代理 after code");
}
}
public class Test {
public static void main(String[] args) {
Order order = new Order();
IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
orderServiceDynamicProxy.saveOrder(order);
}
}
基于子类的动态代理
提供者:第三方的 CGLib
如果报 asmxxxx 异常,需要导入 asm.jar。要求:被代理类不能用 final 修饰的类(最终类)
主要是对指定的类生成一个子类,覆盖其中的方法,来实现代理对象。
public class CglibProxy {
public static<T> T createProxy(T t){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(t.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj,
Method method,
Object[] args,
MethodProxy proxy) throws Throwable {
//可以在前后执行一些方法
Object invoke = proxy.invokeSuper(obj,args);
return invoke;
}
});
Object o = enhancer.create();
return (T) o;
}
}
代理速度对比
JDK动态代理 在万次之内比 CGLib 快
区别-装饰器、代理
装饰器和代理之间的区别很细微,可以认为装饰器是代理的一个子集
静态代理就是装饰器的方式
源码
spring
当Bean有实现接口时,Spring就会用JDK的动态代理
当Bean没有实现接口时, Spring使用CGlib
MyBatis
UserMapper、CityMapper,mybatis帮我们写实现MapperProxy
本文介绍了代理模式的基本概念,如静态代理和动态代理。静态代理通过手动创建代理类实现,而动态代理则分为基于接口的JDK动态代理和基于子类的CGLib动态代理。文章讨论了动态代理在性能上的差异,并指出Spring在创建Bean时会根据接口的存在与否选择使用JDK或CGLib。此外,还提到了MyBatis中的MapperProxy和数据源代理如AlibabaSeata的DataSourceProxy等应用。
1123

被折叠的 条评论
为什么被折叠?



