快速导航
一、代理模式介绍
二、代码演示
三、jdk中使用代理模式的地方
一、代理模式介绍
定义:为其他对象提供一种代理,以控制对这个对象的访问
代理对象在客户端和目标对象之间起到中介作用
适用场景:
保护目标对象
增强目标对象
优点:
代理模式能将代理对象与真实被调用的目标对象分离
一定程度上降低了系统的耦合度,扩展性好
保护目标对象
增强目标对象
缺点:
造成系统设计中类数量的增加
在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
增加系统的复杂性
扩展:
静态代理就是在代码中显示指定的代理;
动态代理无法代理类,但是可以代理接口;
CGLib代理:可以代理类
Spring 代理选择:
当Bean有实现接口时,Spring就会用jdk的动态代理;
当Bean没有实现接口时,Spring使用CGLib;
配置 <aop:aspectj-autoproxy proxy-target-class=“true” />,强制使用CGLib
相关设计模式:
代理模式与装饰者模式
代理模式与适配器模式
二、代码演示
1、静态代理模式
//订单类
public class Order {
private Object OrderInfo;
private Integer userId;
public Object getOrderInfo() {
return OrderInfo;
}
public void setOrderInfo(Object orderInfo) {
OrderInfo = orderInfo;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
}
//订单处理Dao层
public class OrderDao {
public int insert(Order order){
System.out.println("dao层添加order成功");
return 1;
}
}
//订单服务层
public class IOrderService {
public int saveOrder(Order order) {
/** Spring会自己注入,我们这里就直接new出来了 */
OrderDao iOrderDao = new OrderDao();
System.out.println("Service调用Dao层添加Order层");
return iOrderDao.insert(order);
}
}
//设置 db 的路由位置
public class DataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER=new ThreadLocal<>();
public static void setDBType(String dbType){
CONTEXT_HOLDER.set(dbType);
}
public static String getDBType(){
return CONTEXT_HOLDER.get();
}
public static void clearDBType(){
CONTEXT_HOLDER.remove();
}
}
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDBType();
}
}
/**
* @program: adpn-pattern->StaticOrderServiceProxy
* @description: 静态代理类
* @author: Jstar
* @create: 2019-11-30 15:36
**/
public class StaticOrderServiceProxy {
public int saveOrder(Order order){
beforeMethod();
/** 在代理类里面注入目标对象,但最终实现还是由目标类来完成的 */
IOrderService iorderService = new IOrderService();
Integer userId = order.getUserId();
/** 这里就是实现一个分库的功能,对userId取模2,这里就只会得到0或者是1 */
int dbRouter = userId % 2;
System.out.println("静态代理分配到 db"+dbRouter+" 处理数据");
DataSourceContextHolder.setDBType(String.valueOf(dbRouter));
afterMethod();
return iorderService.saveOrder(order);
}
// 增强的 before 方法
private void beforeMethod() {
System.out.println("静态代理 before code");
}
// 增强的 after 方法
private void afterMethod() {
System.out.println("静态代理 after code");
}
}
//测试类
public class Test {
public static void main(String[]args){
Order order = new Order();
order.setUserId(10);
StaticOrderServiceProxy staticOrderServiceProxy = new StaticOrderServiceProxy();
staticOrderServiceProxy.saveOrder(order);
}
}
这是类的uml图:
运行结果:
2、动态代理模式
我们把部分代码改一下:
//IOrderService 改为接口
public interface IOrderService {
public int saveOrder(Order order);
}
//IOrderService 接口的实现
public class IOrderServiceImpl implements IOrderService{
@Override
public int saveOrder(Order order) {
/** Spring会自己注入,我们这里就直接new出来了 */
OrderDao iOrderDao = new OrderDao();
System.out.println("Service调用Dao层添加Order层");
return iOrderDao.insert(order);
}
}
/**
* @program: adpn-pattern->DynamicOrderProxy
* @description: 动态代理类
* @author: Jstar
* @create: 2019-11-30 15:57
**/
public class DynamicOrderProxy implements InvocationHandler {
//这是目标类
private Object target;
//通过构造器把目标类注入进来
public DynamicOrderProxy(Object target) {
this.target = target;
}
//进行绑定
public Object bind(){
Class aClass = target.getClass();
return Proxy.newProxyInstance(aClass.getClassLoader(),aClass.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 argObject) {
int userId = 0;
System.out.println("动态代理before code");
if (argObject instanceof Order) {
Order order = (Order) argObject;
userId = order.getUserId();
}
/** 这里就是实现一个分库的功能,对userId取模2,这里就只会得到0或者是1 */
int dbRouter = userId % 2;
System.out.println("动态代理分配到 db"+dbRouter+" 处理数据");
//todo 设置dataSource;
DataSourceContextHolder.setDBType(String.valueOf(dbRouter));
}
private void afterMethod() {
System.out.println("动态代理after core");
}
}
//测试类
public class Test {
public static void main(String[]args){
Order order = new Order();
order.setUserId(10);
//动态代理
IOrderService iOrderService = (IOrderService) new DynamicOrderProxy(new IOrderServiceImpl()).bind();
iOrderService.saveOrder(order);
}
}
看一下运行结果:
三、代理模式在jdk中的使用
1、AOP
2、org.springframework.aop.framework.ProxyFactoryBean
3、org.springframework.aop.framework.CglibAopProxy