国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術(shù)及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java實現(xiàn)AOP面向切面編程的實例教程

Java實現(xiàn)AOP面向切面編程的實例教程

2020-04-20 14:39elviskang JAVA教程

這篇文章主要介紹了Java實現(xiàn)AOP面向切面編程的實例教程,通常Java中的AOP都是利用Spring框架中造好的輪子來開發(fā),而本文則關(guān)注于Java本身AOP的設計模式實現(xiàn),需要的朋友可以參考下

介紹

眾所周知,AOP(面向切面編程)是Spring框架的特色功能之一。通過設置橫切關(guān)注點(cross cutting concerns),AOP提供了極高的擴展性。那AOP在Spring中是怎樣運作的呢?當你只能使用core java,卻需要AOP技術(shù)時,這個問題的解答變得極為關(guān)鍵。不僅如此,在高級技術(shù)崗位的面試中,此類問題也常作為考題出現(xiàn)。這不,我的朋友最近參加了一個面試,就被問到了這樣一個棘手的問題——如何在不使用Spring及相關(guān)庫,只用core Java的條件下實現(xiàn)AOP。因此,我將在本文中提供一份大綱,幫助大家了解如何只用core Java實現(xiàn)一個AOP(當然啦,這種AOP在功能上有一定的局限性)。注意,本文不是一篇有關(guān)Spring AOP與Java AOP的對比研究,而是有關(guān)在core Java中借助固有的設計模式實現(xiàn)AOP的教程。

想必讀者已經(jīng)知道AOP是什么,也知道在Spring框架中如何使用它,因此本文只著眼于如何在不用Spring的前提下實現(xiàn)AOP。首先,我們得知道,Spring是借助了JDK proxy和CGlib兩種技術(shù)實現(xiàn)AOP的。JDK dynamic proxy提供了一種靈活的方式來hook一個方法并執(zhí)行指定的操作,但執(zhí)行操作時得有一個限制條件:必須先提供一個相關(guān)的接口以及該接口的實現(xiàn)類。實踐出真知,讓我們透過一個案例來理解這句吧!現(xiàn)在有一個計算器程序,用于完成一些數(shù)學運算。讓我們來考慮下除法功能,此時的問題是:如果core framework 已經(jīng)具備了一份實現(xiàn)除法的代碼,我們能否在代碼執(zhí)行時劫持(highjack)它并執(zhí)行額外的校驗呢?答案是肯定的,我將用下面提供的代碼片段來證明這點。首先來看基礎接口的代碼:

?
1
2
3
public interface Calculator {
  public int calculate( int a , int b);
}

該接口實現(xiàn)類的代碼如下:

?
1
2
3
4
5
6
public class CalculatorImpl implements Calculator {
  @Override
  public int calculate(int a, int b) {
    return a/b;
  }
}

假設我們既不能修該上面的代碼,也不能對核心庫進行任何改動,怎樣才能完美地實現(xiàn)校驗功能呢?不如試下JDK dynamic proxy的功能吧。

?
1
2
3
4
5
6
7
8
9
10
11
12
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實現(xiàn)的校驗功能的效果如何。

?
1
2
3
4
5
6
7
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);
  }

從結(jié)果可以看出,簡單地實現(xiàn)功能強大的InvocationHandler接口,我們便能得到一個hooking implementation。按照JDK文檔的描述,InvocationHandler接口是借助一個代理實例(proxy instance)來處理一個方法調(diào)用的。

現(xiàn)在我們已經(jīng)知道,InvocationHandler的invoke()方法能夠幫助我們解決問題。那么再來解決一個新問題——怎樣才能在方法執(zhí)行的前后執(zhí)行操作呢?說的更具體一些,我們能通過添加多個aop(before、after、around)來hook一個方法嗎(譯注:原文為add multiple aops,但我認為Handler是充當Aspect的角色)?答案同樣是肯定的。按照以下的步驟建立一個精簡的代碼模板便能滿足這樣的需求:

  • 創(chuàng)建一個抽象類,用于將aop應用于目標對象上。

  • 創(chuàng)建名為BeforeHandler 和 AfterHandler的兩個aop。前者在方法執(zhí)行之前工作,而后者則在方法執(zhí)行結(jié)束后工作。

  • 創(chuàng)建一個代理類,使所有的aop handler和目標對象只需作為參數(shù)傳入,就能創(chuàng)建一個hook。

  • 加入你自己的業(yè)務邏輯或者橫切關(guān)注點。

  • 最后,通過傳入相關(guān)的參數(shù)創(chuàng)建代理對象(proxy object)。

兩種實現(xiàn)AOP的方式: 

1,JDK提供的動態(tài)代理實現(xiàn)  
接口 

?
1
2
3
4
5
6
7
public interface UserBean
{
  void getUser();
  void addUser();
  void updateUser();
  void deleteUser();
}

原始實現(xiàn)類 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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!"); 
  }    
}

代理類  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
     
    //權(quán)限判斷
    if(userName != null && !"".equals(userName))
    {
      result = method.invoke(targetObject, args);
    }
     
    return result;
  }
}

 
測試類  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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();
         
  }
}

 
輸出:  

?
1
2
3
Proved.............
this is addUser() method!
NO Proved.............

 
從上面這個例子可以成功攔截了調(diào)用的方法addUser()并對其做了相應的處理  
 

2, 通過cglib創(chuàng)建代理類

好處是不要求我們的目標對象實現(xiàn)接口 
原始類 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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;
  }
}

代理類 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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;
  }
}

測試類  

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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();
         
  }
}

 
輸出: 

?
1
2
3
4
.............CGLIB Proxy....................
Proved....................
this is addClient() method!
NO Proved....................

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 观看av| 欧美一级二级三级视频 | 91精品国产一区二区三区四区在线 | 久久成人国产精品 | 欧美日韩视频在线第一区 | 亚洲日韩中文字幕一区 | 在线理论电影 | 欧美日韩中文 | 国产乱码精品一区二区三区中文 | 97精品超碰一区二区三区 | 日韩视频免费 | 国产精品免费高清 | 91精品久久 | 国产98色在线 | 日韩 | 簧片av | 精品无码久久久久久国产 | 在线观看国产一区 | 国产丝袜视频 | 免费精品 | 国产亚洲欧美另类一区二区三区 | 国产精品视频播放 | 成人国产精品视频 | 黄色免费成人 | 久久免费国产 | 精品成人在线 | 欧美精品在线一区二区 | 免费日韩视频 | 国产精品一区二区三区在线播放 | 日本久久久久久久久久久久 | 一区三区在线观看 | 久久66 | 99国产精品99久久久久久 | 综合99 | 欧美精品一区二区三区在线 | 久久久久久亚洲精品 | 国产精品免费久久久久久 | 美女久久久 | 久久久久久成人 | 香蕉av在线 | 999在线观看视频 | 久久久性色精品国产免费观看 |