一、代理模式
一句话总结:为目标对象创建一个代理类,用于控制这个目标对象的访问,一般会在代理类中创建目标对象的实例,客户端使用这个代理类而不会直接使用目标对象
定义 :为其他对象提供一种代理,以控制对这个对象的访问
,代理对象在客户端和目标对象之间起到中介作用类型 :结构型适用场景 :
优点 :
代理模式能将代理对象与真实被调用的目标对象分离
一定程度上降低了系统的耦合度,扩展性好 保护目标对象 增强目标对象 缺点:
代理模式会造成系统设计中类的数目增加 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢 增加系统的复杂度 扩展 :
静态代理
:在代码中显示指定的代理动态代理
:无法代理类,可以代理接口Cglib代理
:可以代理类,针对类实现进行代理,如果代理一个类,Cglib会生成一个被代理类的子类,通过继承覆盖其中的方法,然后还有重写 Spring代理选择
当Bean有实现接口
时,Spring就会用JDK的动态代理 当Bean没有实现接口
时,Spring使用Cglib代理 也可以强制使用Cglib
:在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
相关设计模式 :
代理模式和装饰者模式
:实现上相似,但是目的不同,装饰者模式是为对象加上行为,而代理模式是控制访问
,代理模式更加注重通过设置代理人的方式来增强目标对象,通常使用代理模式时,会在代理类中创建一个对象的实例,而装饰者模式的时候,通常会把原始对象作为一个参数传给装饰者的构造器
代理模式和适配器模式
:适配器模式主要改变所考虑对象的接口,而代理模式是不能改变所代理类的接口的
二、静态代理 Coding
public class Order {
private Object orderInfo;
private Integer userId;
public Object getOrderInfo ( ) {
return orderInfo;
}
public void setOrderInfo ( Object orderInfo) {
this . orderInfo = orderInfo;
}
public Integer getUserId ( ) {
return userId;
}
public void setUserId ( Integer userId) {
this . userId = userId;
}
}
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 OrderServiceStaticProxy {
private IOrderService iOrderService;
public int saveOrder ( Order order) {
beforeMethod ( order) ;
iOrderService = new OrderServiceImpl ( ) ;
int result = iOrderService. saveOrder ( order) ;
afterMethod ( ) ;
return result;
}
private void beforeMethod ( Order order) {
int userId = order. getUserId ( ) ;
int dbRouter = userId % 2 ;
System. out. println ( "静态代理分配到【db" + dbRouter + "】处理数据" ) ;
DataSourceContextHolder. setDBType ( "db" + String. valueOf ( dbRouter) ) ;
System. out. println ( "静态代理 before code" ) ;
}
private void afterMethod ( ) {
System. out. println ( "静态代理 after code" ) ;
}
}
public class Test {
public static void main ( String[ ] args) {
Order order = new Order ( ) ;
order. setUserId ( 2 ) ;
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy ( ) ;
orderServiceStaticProxy. saveOrder ( order) ;
}
}
静态代理分配到【db0】处理数据
静态代理 before code
Service层调用Dao层添加Order
Dao层添加Order成功
静态代理 after code
UML类图 说明:首先,OrderServiceImpl和OrderDaoImpl两个类分别实现了它们的接口,然后静态代理类组合了OrderService接口,同时它又创建了OrderService的实现OrderServiceImpl,是为了增强目标对象。
三、动态代理 Coding
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 + "】处理数据" ) ;
}
private void afterMethod ( ) {
System. out. println ( "动态代理 after code" ) ;
}
}
public class Test {
public static void main ( String[ ] args) {
Order order = new Order ( ) ;
order. setUserId ( 1 ) ;
IOrderService orderServiceDynamicProxy =
( IOrderService) new OrderServiceDynamicProxy ( new OrderServiceImpl ( ) ) . bind ( ) ;
orderServiceDynamicProxy. saveOrder ( order) ;
}
}
动态代理 before code
动态代理分配到【db1】处理数据
Service层调用Dao层添加Order
Dao层添加Order成功
动态代理 after code
说明:动态代理核心在于Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this)
,可以断点跟踪里面的逻辑调用
四、源码中的应用
org.springframework.aop.framework.ProxyFactoryBean :代理工厂Bean,核心方法是getObject()
public Object getObject ( ) throws BeansException {
this . initializeAdvisorChain ( ) ;
if ( this . isSingleton ( ) ) {
return this . getSingletonInstance ( ) ;
} else {
if ( this . targetName == null) {
this . logger. warn ( "Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property." ) ;
}
return this . newPrototypeInstance ( ) ;
}
}
org.springframework.aop.framework.JdkDynamicAopProxy :JDK动态代理org.springframework.aop.framework.CglibAopProxy :对类进行代理增强org.apache.ibatis.binding.MapperProxyFactory :Mapper代理工厂