java設計模式——動態代理示例
阿新 • • 發佈:2021-01-07
技術標籤:java設計模式
動態代理示例實現動態分庫功能示例
1、程式碼結構如下圖:
2、建立訂單和使用者類
package com.rf.designPatterns.structural.proxy;
/**
* @description: 訂單和使用者類
* @author: xz
*/
public class Order {
private Object orderId;//訂單id
private Integer userId;//使用者id
public Object getOrderId() {
return orderId;
}
public void setOrderId(Object orderId) {
this.orderId = orderId;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
}
3、建立Service層
package com.rf.designPatterns.structural.proxy;
/**
* @description: Service層
* @author: xz
*/
public interface OrderService {
int saveOrder(Order order);
}
4、建立Dao層
package com.rf.designPatterns.structural.proxy;
/**
* @description: Dao層
* @author: xz
*/
public interface OrderDao {
int insert(Order order);
}
5、建立Dao實現層
package com.rf.designPatterns.structural.proxy;
/**
* @description: Dao實現層
* @author: xz
*/
public class OrderDaoImpl implements OrderDao{
@Override
public int insert(Order order) {
System.out.println("Dao層新增訂單成功");
return 1;
}
}
6、建立Service實現層
package com.rf.designPatterns.structural.proxy;
/**
* @description: Service實現層
* @author: xz
*/
public class OrderServiceImpl implements OrderService{
private OrderDao orderDao;
@Override
public int saveOrder(Order order) {
//spring會自動注入,這裡我們自己直接new
orderDao=new OrderDaoImpl();
System.out.println("Service呼叫Dao層的inser方法新增訂單");
orderDao.insert(order);
return 1;
}
}
7、建立資料來源上下文類
package com.rf.designPatterns.structural.proxy.db;
/**
* @description: 資料來源上下文類
* @author: xz
*/
public class DataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER=new ThreadLocal<String>();
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();
}
}
8、建立動態的資料來源類
package com.rf.designPatterns.structural.proxy.db;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @description: 動態的資料來源類
* @author: xz
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDBType();
}
}
9、建立Service層的動態代理
package com.rf.designPatterns.structural.proxy.dynamicProxy;
import com.rf.designPatterns.structural.proxy.Order;
import com.rf.designPatterns.structural.proxy.db.DataSourceContextHolder;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @description: Service層的動態代理
* @author: xz
*/
public class OrderServiceDynamicProxy implements InvocationHandler {
//宣告一個目標物件
private Object target;
//通過構造器新增目標物件
public OrderServiceDynamicProxy(Object target) {
this.target = target;
}
//繫結目標物件
public Object bind(){
Class cls=target.getClass();//獲取目標類的class物件
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),this);
}
/**
* @param proxy 動態生成的代理類
* @param method 要被增強的方法物件
* @param args method方法的引數
* @return
* @throws Throwable
*/
@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){
System.out.println("動態代理before程式碼, 在invoke方法之前執行");
int userId=0;
if(obj instanceof Order){
Order order=(Order)obj;
userId= order.getUserId();
}
int dbRouter=userId % 2;
System.out.println("動態代理分配到 db【" +dbRouter+ "】 資料庫處理資料");
DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter));
}
private void afterMethod(){
System.out.println("動態代理after程式碼, 在invoke方法之後執行");
}
}
10、建立測試類
package com.rf.designPatterns.structural.proxy.dynamicProxy;
import com.rf.designPatterns.structural.proxy.Order;
import com.rf.designPatterns.structural.proxy.OrderService;
import com.rf.designPatterns.structural.proxy.OrderServiceImpl;
public class Test {
public static void main(String[] args) {
Order order=new Order();
//order.setUserId(1);
order.setUserId(2);
OrderService orderServiceDynamicProxy = (OrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind();
orderServiceDynamicProxy.saveOrder(order);
}
}
11、測試結果如下圖: