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....................