標籤:
在上篇部落格中個,咱們一起組建了一個容器,裡面封裝了業務,這樣,咱們就將業務和服務的組裝放到了用戶端,而用戶端就相當於咱們的開發中使用到的設定檔,大家發現問題了嗎?就是我不能動態改動了?業務容器在代理完成後,重新添加一個容器,這時候,是不被允許的,那這個容器就是個編譯時間起作用的容器,他就喪失了很多的靈活性! 那怎麼辦呢?實際就是調換一下調用順序就好,大家看看結果:
1,類圖對比
改造後類圖
2,代碼實現:2.1代理類的變化:
/** * 打招呼動態代理類,給業務類添加功能 * 前一版本為JDK代理實現 * 本次添加執行方法之前列印到控制台‘befor’ * 本次添加執行方法之後列印到控制台‘after’ *本次版本為DGLIB代理 * 換代理類原因,JDK代理要求被代理類必須實現某介面,因為它底層實現是建立一個類,實現和被代理類相同的介面 * 用代理類建立的業務類代替原業務類 * CGLIB代理是建立一個類,繼承自被代理類,用建立的代理類替換掉原業務類,就不需要介面了 * *5.0版本增加服務組裝容器,將服務從代理類中抽離出去了,我們的代理類成為了一個bean *6.0將服務容器定義為介面 *7.0增加業務容器 *8.0 業務容器不靈活,將擷取代理放置到業務容器端,實現動態增加元素,也能拿到代理 * @author 許恕 * @version 3.0.0 , 2015年6月16日 下午3:20:13 */public class CGLibDynamicProxy implements MethodInterceptor { //服務類容器 private IProxyMehds proxyMehds; //代理工廠類:單例模式,最佳化記憶體開銷 private static CGLibDynamicProxy instance = new CGLibDynamicProxy(); //建構函式 private CGLibDynamicProxy() { } //擷取cglib代理工廠類 public static CGLibDynamicProxy getInstance() { return instance; } /** * 使用代理工廠產生某個類的代理 * * @param cls 要代理的類 * @return 返回已經代理好的類 */ @SuppressWarnings("unchecked") public <T> T getProxy(Class<T> cls) { return (T) Enhancer.create(cls, this); } //重寫被代理對象的方法執行 //所有的方法執行,到反射的層級都是invoke,重寫了這個方法,就重寫了所有的方法執行,實現了代理 @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { //重要改進:從服務容器中執行方法,不再是寫死的! proxyMehds.beforeBean(); //方法正常執行的語句 Object result = proxy.invokeSuper(target, args); //重要改進:從服務容器中執行方法,不再是寫死的! proxyMehds.afterBean(); return result; } //服務容器的get方法 public IProxyMehds getProxyMehds() { return proxyMehds; } //服務容器的set方法 public void setProxyMehds(IProxyMehds proxyMehds) { this.proxyMehds = proxyMehds; }}
2.2業務容器
/** * 業務類容器: * 用map盛放要切入服務的業務類 * * @author 許恕 * @version 3.0.0 , 2015-6-29 14:25:21 */public class DoMehds implements IDoMehds { //盛放執行業務的map private HashMap<String,Object> DoBeans; //代理類 private CGLibDynamicProxy proxy ; /** * 封裝擷取元素的方法,每次擷取元素都封裝一個代理 * * @param 元素的名字 * @return 代理好的元素 */ public Object getBean(String beanName){ return proxy.getProxy(DoBeans.get(beanName).getClass()); } //擷取業務map public HashMap<String, Object> getDoBeans() { return DoBeans; } //設定業務map public void setDoBeans(HashMap<String, Object> doBeans) { DoBeans = doBeans; } //擷取代理類 public CGLibDynamicProxy getProxy() { return proxy; } //設定代理類 public void setProxy(CGLibDynamicProxy proxy) { this.proxy = proxy; }}
2.3 用戶端
/** * 執行代理程式的用戶端 * * @author 許恕 * @version 3.0.0 , 2015年6月16日 下午3:18:42 */public class Client { //用戶端執行的主方法:系統規定 public static void main(String[] args) { //盛放方法執行前的對象的容器 HashMap<String,Object> beforBeans; HashMap<String,Object> afterBeans; //配製方法執行前要執行哪些方法 HashMap<String,String> beforMethods; HashMap<String,String> afterMethods; //執行個體以上定義的服務類map beforMethods=new HashMap(); beforBeans=new HashMap(); afterMethods=new HashMap(); afterBeans=new HashMap(); //將服務類AspectClass1添加到方法執行要載入的服務類 beforBeans.put("AspectClass1", new AspectClass1()); beforBeans.put("AspectClass2", new AspectClass2()); afterBeans.put("AspectClass3", new AspectClass3()); afterBeans.put("AspectClass4", new AspectClass4()); //規定每個服務類要執行的方法 beforMethods.put("AspectClass1", "SayHello"); beforMethods.put("AspectClass2", "SayGoodBye"); afterMethods.put("AspectClass3", "SayHi"); afterMethods.put("AspectClass4", "Eat"); //執行個體服務類容器,將四個map傳入容器中 ProxyMehds proxyMehds =new ProxyMehds(); proxyMehds.setBeforBeans(beforBeans); proxyMehds.setBeforMethods(beforMethods); proxyMehds.setAfterBeans(afterBeans); proxyMehds.setAfterMethods(afterMethods); //執行個體業務map HashMap<String,Object> DoBeansMap = new HashMap<String,Object> (); //將業務裝載到map中 DoBeansMap.put("dobeans1", new GreetingImpl()); DoBeansMap.put("dobeans2", new EatClass()); //將業務map裝載到容器中 DoMehds doMehds = new DoMehds(); doMehds.setDoBeans(DoBeansMap); //執行個體代理類 CGLibDynamicProxy cglib =CGLibDynamicProxy.getInstance(); //接受切面 cglib.setProxyMehds(proxyMehds); doMehds.setProxy(cglib); //接受要代理的對象 Greeting greeting = (Greeting)doMehds.getBean("dobeans1"); EatClass eatObject = (EatClass)doMehds.getBean("dobeans2"); //執行對象的某個方法 greeting.sayHello("Jack"); eatObject.Eat(); } }
3,總結
代碼的靈活,就像生活一般,在代碼靈活的過程中,我們就會對比下生活,生活中,我們每個人,事,物都是獨立的對象,而在生活中的時間軸中,我們也是過程化的組織,我們的代碼和生活,在思想上都是相同的,最佳化的不僅僅是代碼,還有思想啊!
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
java架構解密——即時動態aop