一、基本概念
代理模式是指为其他对象提供的一种代理,以控制对这个对象的访问。代理对象在客户端与目标对象之间起到中介作用,属于结构型设计模式。可以保护目标对象,增强目标对象。
二、生活实例
房产中介~
三、代码实例
/**
* @description:订单类
* @author: annecheng,2019-06-29 17:42
*/
public class Order {
public Object orderInfo;
public String orderId;
public Long createTime; //订单创建时间,根据订单的创建时间进行按年分库
public Object getOrderInfo() {
return orderInfo;
}
public void setOrderInfo(Object orderInfo) {
this.orderInfo = orderInfo;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
}
/**
* @description:操作数据库
* @author: annecheng,2019-06-29 17:44
*/
public class OrderDao {
public int insert(Order order){
System.out.println("OrderDao创建order成功!");
return 1;
}
}
/**
* @description:服务类
* @author: annecheng,2019-06-29 18:10
*/
public interface OrderService{
int createOrder(Order order);
}
/**
* @description: 实现类
* @author: annecheng,2019-06-29 18:11
*/
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao;
public OrderServiceImpl(){
orderDao = new OrderDao();
}
public int createOrder(Order order) {
System.out.println("OrderServiceImpl调用OrderDao创建订单");
return orderDao.insert(order);
}
}
类图:
3.1 静态代理
/**
* @description:静态代理实现动态切换数据源
* @author: annecheng,2019-06-29 18:21
*/
public class OrderServiceStaticProxy implements OrderService {
private SimpleDateFormat year = new SimpleDateFormat("yyyy");
private OrderService orderService;
public OrderServiceStaticProxy(OrderService orderService) {
this.orderService = orderService;
}
private void beforeCreate(Order order) {
System.out.println("before create");
Integer dbRouter = Integer.valueOf(year.format(new Date(order.getCreateTime())));
System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据");
}
public int createOrder(Order order) {
beforeCreate(order);
int result = this.orderService.createOrder(order);
afterCreate(order);
return result;
}
private void afterCreate(Order order) {
System.out.println("恭喜你,已经创建成功哦~" + JSONObject.toJSONString(order));
}
}
静态代理:可以对代理的对象进行包装增强
3.2 动态代理
/**
* @description:动态代理
* @author: annecheng,2019-06-29 19:55
*/
public class OrderServiceDynamicProxy implements InvocationHandler {
private Object target;
private SimpleDateFormat year = new SimpleDateFormat("yyyy");
public Object getInstance(Object object){
this.target = object;
Class<?> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(args[0]);
Object obj = method.invoke(this.target, args);
after(args[0]);
return obj;
}
private void before(Object target){
System.out.println("before create");
try {
// 利用反射
Long time = (Long) target.getClass().getMethod("getCreateTime").invoke(target);
Integer dbRouter = Integer.valueOf(year.format(new Date(time)));
System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据");
}catch (Exception e){
System.out.println("异常:" + e);
}
}
private void after(Object target){
System.out.println("已找到,请确认");
}
}
动态代理:代理的对象可以是不再是单纯的一类。
JDK的动态实现原理:
1、拿到被代理类的引用,并且获取它的所有的接口(通过反射获取);
2、JDK Proxy类重新生成一个新的类,实现了被代理类所有接口中的方法;
3、动态生成JAVA代码,把增强的逻辑加入到新生成的代码中。
4、编译生成新的java代码的class文件
5、加载并重新运行新的class,得到的类就是全新的类。
四、总结
目的:保护目标对象 + 增强目标对象
静态代理:对对象本身有限制,显示声明被代理对象,代理的对象很明确。
动态代理:取消了对象类型的限制,更易于扩展。
静态代理类似于家长给儿子找对象,一般只会给儿子找哈。
静态代理类似于婚介所找对象,是不区分人的。
静态代理的缺点:被代理对象有变动,代理对象就需要跟着改变,不符合开闭原则
动态代理:目标对象的职能发生改变,代理类不需要改变
优点:
代理模式能将代理对象与真实的被调用目标对象分离;
一定程度上降低了系统的耦合程度,易于扩展;
代理可以起到保护目标对象的作用;
增加目标对象的职责;
缺点:
造成系统设计中类的数目的增加;
在客户端和目标对象之间增加了一个代理对象,会造成请求处理速度变慢;
增加了系统的复杂度;