1. 程式人生 > >Java高階特性—反射和動態代理

Java高階特性—反射和動態代理

1).反射
  通過反射的方式可以獲取class物件中的屬性、方法、建構函式等,一下是例項:

2).動態代理
  使用場景:  

    在之前的程式碼呼叫階段,我們用action呼叫service的方法實現業務即可。
    由於之前在service中實現的業務可能不能夠滿足當先客戶的要求,需要我們重新修改service中的方法,
    但是service的方法不只在我們這個模組使用,在其他模組也在呼叫,其他模組呼叫的時候,
    現有的service方法已經能夠滿足業務需求,所以我們不能只為了我們的業務而修改service,導致其他模組授影響。
    那怎麼辦呢?
    可以通過動態代理的方式,擴充套件我們的service中的方法實現,使得在原有的方法中增加更多的業務,
    而不是實際修改service中的方法,這種實現技術就叫做動態代理。

  動態代理:在不修改原業務的基礎上,基於原業務方法,進行重新的擴充套件,實現新的業務。

  底層是位元組碼增強技術,常用ASM,CGLIB,javasist等

3).代理實現流程:
  1、書寫代理類和代理方法,在代理方法中實現代理Proxy.newProxyInstance
  2、代理中需要的引數分別為:被代理的類的類載入器soneObjectclass.getClassLoader(),
    被代理類的所有實現介面new Class[] { Interface.class },控制代碼方法new InvocationHandler()
  3、在控制代碼方法中複寫invoke方法,invoke方法的輸入有3個引數Object proxy(代理類物件),
    Method method(被代理類的方法),Object[] args(被代理類方法的傳入引數),
    在這個方法中,我們可以定製化的開發新的業務。
  4、獲取代理類,強轉成被代理的介面
  5、最後,我們可以像沒被代理一樣,呼叫介面的認可方法,方法被呼叫後,方法名和引數列表將被傳入代理類的invoke方法中,進行新業務的邏輯流程。

  1)原業務介面IBoss

public interface IBoss {//介面
    int yifu(String size);
}

  2)原業務實現類

public class Boss implements IBoss{
    public int yifu(String size){
        System.err.println("天貓小強旗艦店,老闆給客戶發快遞----衣服型號:"+size);
        //這件衣服的價錢,從資料庫讀取
        return 50;
    }
    public void kuzi(){
        System.err.println(
"天貓小強旗艦店,老闆給客戶發快遞----褲子"); } }

  3)原業務呼叫

public class SaleAction {
    @Test
    public void saleByBossSelf() throws Exception {
        IBoss boss = new Boss();
        System.out.println("老闆自營!");
        int money = boss.yifu("xxl");
        System.out.println("衣服成交價:" + money);
    }
}

  4)代理類

public static IBoss getProxyBoss(final int discountCoupon) throws Exception {
                Object proxedObj = Proxy.newProxyInstance(Boss.class.getClassLoader(),
                        new Class[] { IBoss.class }, new InvocationHandler() {
                            public Object invoke(Object proxy, Method method,
                                    Object[] args) throws Throwable {
                                    Integer returnValue = (Integer) method.invoke(new Boss(),
                                            args);// 呼叫原始物件以後返回的值
                                    return returnValue - discountCoupon;
                            }
                        });
                return (IBoss)proxedObj;
            }
    }

  5)新業務呼叫

public class ProxySaleAction {
        @Test
        public void saleByProxy() throws Exception {
            IBoss boss = ProxyBoss.getProxyBoss(20);// 將代理的方法例項化成介面
            System.out.println("代理經營!");
            int money = boss.yifu("xxl");// 呼叫介面的方法,實際上呼叫方式沒有變
            System.out.println("衣服成交價:" + money);
        }
}