Java完成AOP面向切面編程的實例教程。本站提示廣大學習愛好者:(Java完成AOP面向切面編程的實例教程)文章只能為提供參考,不一定能成為您想要的結果。以下是Java完成AOP面向切面編程的實例教程正文
引見
盡人皆知,AOP(面向切面編程)是Spring框架的特點功效之一。經由過程設置橫切存眷點(cross cutting concerns),AOP供給了極高的擴大性。那AOP在Spring中是如何運作的呢?當你只能應用core java,卻須要AOP技巧時,這個成績的解答變得極其症結。不只如斯,在高等技巧崗亭的面試中,此類成績也常作為考題湧現。這不,我的同伙比來加入了一個面試,就被問到了如許一個辣手的成績——若何在不應用Spring及相干庫,只用core Java的前提下完成AOP。是以,我將在本文中供給一份年夜綱,贊助年夜家懂得若何只用core Java完成一個AOP(固然啦,這類AOP在功效上有必定的局限性)。留意,本文不是一篇有關Spring AOP與Java AOP的比較研討,而是有關在core Java中借助固有的設計形式完成AOP的教程。
想必讀者曾經曉得AOP是甚麼,也曉得在Spring框架中若何應用它,是以本文只著眼於若何在不消Spring的條件下完成AOP。起首,我們得曉得,Spring是借助了JDK proxy和CGlib兩種技巧完成AOP的。JDK dynamic proxy供給了一種靈巧的方法來hook一個辦法並履行指定的操作,但履行操作時得有一個限制前提:必需先供給一個相干的接口和該接口的完成類。理論出真知,讓我們透過一個案例來懂得這句吧!如今有一個盤算器法式,用於完成一些數學運算。讓我們來斟酌下除法功效,此時的成績是:假如core framework 曾經具有了一份完成除法的代碼,我們可否在代碼履行時劫持(highjack)它並履行額定的校驗呢?謎底是確定的,我將用上面供給的代碼片斷來證實這點。起首來看基本接口的代碼:
public interface Calculator { public int calculate( int a , int b); }
該接話柄現類的代碼以下:
public class CalculatorImpl implements Calculator { @Override public int calculate(int a, int b) { return a/b; } }
假定我們既不克不及修該下面的代碼,也不克不及對焦點庫停止任何修改,如何能力完善地完成校驗功效呢?不如試下JDK dynamic proxy的功效吧。
public class SomeHandler implements InvocationHandler { // Code omitted for simplicity….. @Override public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { // Your complex business validation and logic Object result = method.invoke(targetObject ,params); return result; } }
讓我們經由過程測試類來看看由JDK dynamic proxy完成的校驗功效的後果若何。
public static void main(String[] args) { CalculatorImpl calcImpl = new CalculatorImpl(); Calculator proxied = (Calculator)ProxyFactory.getProxy (Calculator.class, calcImpl, new SomeHandler(calcImpl)); int result = proxied.calculate(20, 10); System.out.println("FInal Result :::" + result); }
從成果可以看出,簡略地完成功效壯大的InvocationHandler接口,我們便能獲得一個hooking implementation。依照JDK文檔的描寫,InvocationHandler接口是借助一個署理實例(proxy instance)來處置一個辦法挪用的。
如今我們曾經曉得,InvocationHandler的invoke()辦法可以或許贊助我們處理成績。那末再來處理一個新成績——如何能力在辦法履行的前後履行操作呢?說的更詳細一些,我們能經由過程添加多個aop(before、after、around)來hook一個辦法嗎(譯注:原文為add multiple aops,但我以為Handler是充任Aspect的腳色)?謎底異樣是確定的。依照以下的步調樹立一個精簡的代碼模板便能知足如許的需求:
兩種完成AOP的方法:
1,JDK供給的靜態署理完成
接口
public interface UserBean { void getUser(); void addUser(); void updateUser(); void deleteUser(); }
原始完成類
public class UserBeanImpl implements UserBean { private String user = null; public UserBeanImpl() { } public UserBeanImpl(String user) { this.user = user; } public String getUserName() { return user; } public void getUser() { System.out.println("this is getUser() method!"); } public void setUser(String user) { this.user = user; System.out.println("this is setUser() method!"); } public void addUser() { System.out.println("this is addUser() method!"); } public void updateUser() { System.out.println("this is updateUser() method!"); } public void deleteUser() { System.out.println("this is deleteUser() method!"); } }
署理類
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.cignacmc.finance.bean.UserBeanImpl; public class UserBeanProxy implements InvocationHandler { private Object targetObject; public UserBeanProxy(Object targetObject) { this.targetObject = targetObject; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { UserBeanImpl userBean = (UserBeanImpl) targetObject; String userName = userBean.getUserName(); Object result = null; //權限斷定 if(userName != null && !"".equals(userName)) { result = method.invoke(targetObject, args); } return result; } }
測試類
import java.lang.reflect.Proxy; import com.cignacmc.finance.bean.UserBean; import com.cignacmc.finance.bean.UserBeanImpl; import com.cignacmc.finance.proxy.UserBeanProxy; public class ProxyExe { public static void main(String[] args) { System.out.println("Proved............."); UserBeanImpl targetObject = new UserBeanImpl("Bob Liang"); UserBeanProxy proxy = new UserBeanProxy(targetObject); //生成署理對象 UserBean object = (UserBean)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), proxy); object.addUser(); System.out.println("NO Proved............."); targetObject = new UserBeanImpl(); proxy = new UserBeanProxy(targetObject); //生成署理對象 object = (UserBean)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), proxy); object.addUser(); } }
輸入:
Proved............. this is addUser() method! NO Proved.............
從下面這個例子可以勝利攔阻了挪用的辦法addUser()並對其做了響應的處置
2, 經由過程cglib創立署理類
利益是不請求我們的目的對象完成接口
原始類
public class ClientBean { private String name = null; public ClientBean() { } public ClientBean(String name) { this.name = name; } public void addClient() { System.out.println("this is addClient() method!"); } public void deleteClient() { System.out.println("this is deleteClient() method!"); } public void getClient() { System.out.println("this is getClient() method!"); } public void updateClient() { System.out.println("this is updateClient() method!"); } public String getClientName() { return name; } public void setClientName(String name) { this.name = name; } }
署理類
import java.lang.reflect.Method; import com.cignacmc.finance.bean.ClientBean; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLibProxy implements MethodInterceptor { private Object targetObject; public Object createProxyObject(Object targetObject) { this.targetObject = targetObject; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { ClientBean clientBean = (ClientBean)targetObject; String userName = clientBean.getClientName(); Object result = null; if(userName != null && !"".equals(userName)) { result = method.invoke(targetObject, args); } return result; } }
測試類
import java.lang.reflect.Proxy; import com.cignacmc.finance.bean.ClientBean; import com.cignacmc.finance.bean.UserBean; import com.cignacmc.finance.bean.UserBeanImpl; import com.cignacmc.finance.proxy.CGLibProxy; import com.cignacmc.finance.proxy.UserBeanProxy; public class ProxyExe { public static void main(String[] args) { System.out.println(".............CGLIB Proxy...................."); System.out.println("Proved...................."); CGLibProxy cproxy = new CGLibProxy(); ClientBean clientBean = (ClientBean)cproxy.createProxyObject(new ClientBean("Bob Liang")); clientBean.addClient(); System.out.println("NO Proved...................."); cproxy = new CGLibProxy(); clientBean = (ClientBean)cproxy.createProxyObject(new ClientBean()); clientBean.addClient(); } }
輸入:
.............CGLIB Proxy.................... Proved.................... this is addClient() method! NO Proved....................