Aspect Oriented Programming 面向切面編程。解耦是程序員編碼開發過程當中一直追求的。AOP也是爲了解耦所誕生。程序員
具體思想是:定義一個切面,在切面的縱向定義處理方法,處理完成以後,回到橫向業務流。編程
AOP 在Spring框架中被做爲核心組成部分之一,的確Spring將AOP發揮到很強大的功能。最多見的就是事務控制。工做之餘,對於使用的工具,難免須要瞭解其因此然。學習了一下,寫了些程序幫助理解。設計模式
AOP 主要是利用代理模式的技術來實現的。框架
一、靜態代理:就是設計模式中的proxy模式ide
a、業務接口工具
/** * 抽象主題角色:聲明瞭真實主題和代理主題的共同接口。 * * @author yanbin * */ public interface ITalk { public void talk(String msg); }
b、業務實現學習
/** * 真實主題角色:定義真實的對象。 * * @author yanbin * */ public class PeopleTalk implements ITalk { public String username; public String age; public PeopleTalk(String username, String age) { this.username = username; this.age = age; } public void talk(String msg) { System.out.println(msg + "!你好,我是" + username + ",我年齡是" + age); } public String getName() { return username; } public void setName(String name) { this.username = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
c、代理對象測試
/** * 代理主題角色:內部包含對真實主題的引用,而且提供和真實主題角色相同的接口。 * * @author yanbin * */ public class TalkProxy implements ITalk { private ITalk talker; public TalkProxy(ITalk talker) { // super(); this.talker = talker; } public void talk(String msg) { talker.talk(msg); } public void talk(String msg, String singname) { talker.talk(msg); sing(singname); } private void sing(String singname) { System.out.println("唱歌:" + singname); } }
d、測試類this
/** * 代理測試類,使用代理 * * @author yanbin * */ public class ProxyPattern { public static void main(String[] args) { // 不須要執行額外方法的。 ITalk people = new PeopleTalk("AOP", "18"); people.talk("No ProXY Test"); System.out.println("-----------------------------"); // 須要執行額外方法的(切面) TalkProxy talker = new TalkProxy(people); talker.talk("ProXY Test", "代理"); } }
從這段代碼能夠看出來,代理模式其實就是AOP的雛形。 上端代碼中talk(String msg, String singname)是一個切面。在代理類中的sing(singname)方法是個後置處理方法。編碼
這樣就實現了,其餘的輔助方法和業務方法的解耦。業務不須要專門去調用,而是走到talk方法,瓜熟蒂落的調用sing方法
再從這段代碼看:一、要實現代理方式,必需要定義接口。二、每一個業務類,須要一個代理類。
二、動態代理:jdk1.5中提供,利用反射。實現InvocationHandler接口。
業務接口仍是必須得,業務接口,業務類同上。
a、代理類:
/** * 動態代理類 * * @author yanbin * */ public class DynamicProxy implements InvocationHandler { /** 須要代理的目標類 */ private Object target; /** * 寫法固定,aop專用:綁定委託對象並返回一個代理類 * * @param delegate * @return */ public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * @param Object * target:指被代理的對象。 * @param Method * method:要調用的方法 * @param Object * [] args:方法調用時所須要的參數 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; // 切面以前執行 System.out.println("切面以前執行"); // 執行業務 result = method.invoke(target, args); // 切面以後執行 System.out.println("切面以後執行"); return result; } }
b、測試類
/** * 測試類 * * @author yanbin * */ public class Test { public static void main(String[] args) { // 綁定代理,這種方式會在全部的方法都加上切面方法 ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk()); iTalk.talk("業務說明"); } }
輸出結果會是:
切面以前執行
people talk業務說法
切面以後執行
說明只要在業務調用方法切面以前,是能夠動態的加入須要處理的方法。
從代碼來看,若是再創建一個業務模塊,也只須要一個代理類。ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk()); 將業務接口和業務類綁定到動態代理類。
可是這種方式:仍是須要定義接口。
三、利用cglib
CGLIB是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強。採用的是繼承的方式。不細說,看使用
a、業務類
/** * 業務類 * * @author yanbin * */ public class PeopleTalk { public void talk(String msg) { System.out.println("people talk" + msg); } }
b、cglib代理類
/** * 使用cglib動態代理 * * @author yanbin * */ public class CglibProxy implements MethodInterceptor { private Object target; /** * 建立代理對象 * * @param target * @return */ public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回調方法 enhancer.setCallback(this); // 建立代理對象 return enhancer.create(); } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object result = null; System.out.println("事物開始"); result = methodProxy.invokeSuper(proxy, args); System.out.println("事物結束"); return result; } }
c.測試類
/** * 測試類 * * @author yanbin * */ public class Test { public static void main(String[] args) { PeopleTalk peopleTalk = (PeopleTalk) new CglibProxy().getInstance(new PeopleTalk()); peopleTalk.talk("業務方法"); peopleTalk.spreak("業務方法"); } }
最後輸出結果:
事物開始
people talk業務方法
事物結束
事物開始
spreak chinese業務方法
事物結束
因爲篇幅有限,這篇主要對AOP的原理簡單實現作了演示和闡述,有助本身理解。至於Spring的AOP實現上面無外乎其右,不過實現方面複雜的多。