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); } }