代理模式(一)

代理模式(Proxy Pattern)是指爲其餘對象提供一種代理,以控制對這個對象的訪問。數據庫

代理對象在客戶端和目標對象之間起到中介做用。屬於結構型設計模式設計模式

適用場景:  1 保護目標對象 2 加強目標對象ide

靜態代理: 顯式聲明被代理對象this

缺點: 不符合開閉原則spa

public interface Person {

    void findLove();
}
public class Son implements Person{

    @Override
    public void findLove(){
        System.out.println("兒子要求:膚白貌美大長腿");
    }

    public void findJob(){

    }

    public void eat(){

    }

}
public class Father implements Person {
    private Son person;

    public Father(Son person){
        this.person = person;
    }

    public void findLove(){
        System.out.println("父親物色對象");
        this.person.findLove();
        System.out.println("雙方父母贊成,確立關係");
    }

    public void findJob(){

    }


}
public static void main(String[] args) {

    Father father = new Father(new Son());
    father.findLove();
  
}

//經常使用的一種靜態代理的形式:對數據庫進行分庫分表 ,hreadLocal 進行數據源動態切換設計

public class Order {
    private Object orderInfo;
    //訂單建立時間進行按年分庫
    private Long createTime;
    private String id;

    public Object getOrderInfo() {
        return orderInfo;
    }

    public void setOrderInfo(Object orderInfo) {
        this.orderInfo = orderInfo;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Long createTime) {
        this.createTime = createTime;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
public class OrderDao {
    public int insert(Order order){
        System.out.println("OrderDao建立Order成功!");
        return 1;
    }
}
public interface IOrderService {
    int createOrder(Order order);
}
public class OrderService implements IOrderService {
    private OrderDao orderDao;

    public OrderService(){
        //若是使用Spring應該是自動注入的
        //咱們爲了使用方便,在構造方法中將orderDao直接初始化了
        orderDao = new OrderDao();
    }

    public int createOrder(Order order) {
        System.out.println("OrderService調用orderDao建立訂單");
        return orderDao.insert(order);
    }
}
public class DynamicDataSourceEntity {

    // 默認數據源
    public final static String DEFAULT_SOURCE = null;

    private final static ThreadLocal<String> local = new ThreadLocal<String>();

    private DynamicDataSourceEntity(){}

    /**
     * 清空數據源
     */
    public static void clear() {
        local.remove();
    }

    /**
     * 獲取當前正在使用的數據源名字
     */
    public static String get(){return  local.get();}

    /**
     * 還原當前切面的數據源
     */
    public static void restore(){
         local.set(DEFAULT_SOURCE);
    }

    /**
     * 設置已知名字的數據源
     * @param source
     */
    public static void set(String source){local.set(source);}

    /**
     * 根據年份動態設置數據源
     * @param year
     */
    public static void set(int year){local.set("DB_" + year);}

}
public class OrderServiceStaticProxy implements IOrderService {
    private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");

    private IOrderService orderService;
    public OrderServiceStaticProxy(IOrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public int createOrder(Order order) {
        Long time = order.getCreateTime();
        Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time)));
        System.out.println("靜態代理類自動分配到【DB_" +  dbRouter + "】數據源處理數據" );
        DynamicDataSourceEntity.set(dbRouter);

        this.orderService.createOrder(order);
        DynamicDataSourceEntity.restore();

        return 0;
    }
}
public static void main(String[] args) {
    try {
        Order order = new Order();

       SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date date = sdf.parse("2019/04/02");
        order.setCreateTime(date.getTime());
        IOrderService orderService = new OrderServiceStaticProxy(new OrderService());
        orderService.createOrder(order);
    }catch (Exception e){
        e.printStackTrace();
    }

}

動態代理: 動態配置和替換被代理對象代理

JDK動態代理的實現原理:rest

    1 拿到被代理類的引用,而且獲取它的全部的接口(反射獲取)orm

    2 JDK Proxy類從新生成一個新的類,實現了被代理類全部接口的方法對象

    3 動態生成Java代碼,把加強邏輯加入到新生成代碼中

    4 編譯生成新的Java代碼的class文件

    5 加載並從新運行新的class,獲得類就是全新類

public interface Person {

    void findLove();
}
public class Girl implements Person {
    public void findLove() {
        System.out.println("高富帥");
        System.out.println("身高180cm");
        System.out.println("有6塊腹肌");
    }
}
public class JDKMeipo implements InvocationHandler {

    private Object target;
    public Object getInstance(Object target) throws Exception{
        this.target = target;
        Class<?> clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj = method.invoke(this.target,args);
        after();
       return obj;
    }

    private void before(){
        System.out.println("我是媒婆,我要給你找對象,如今已經確認你的需求");
        System.out.println("開始物色");
    }

    private void after(){
        System.out.println("OK的話,準備辦事");
    }
}
public static void main(String[] args) {
        try {

            Object obj = new JDKMeipo().getInstance(new Girl());
            Method method = obj.getClass().getMethod("findLove", null);
            method.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

JDK動態代理中要求目標類實現的接口數量不能超過65535個:

 JVM在class文件定義時,規定interface的類型是u2,2個字節,16位,那麼最多支持2的16次方-1,也就是65535

相關文章
相關標籤/搜索