程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java完成AOP面向切面編程的實例教程

Java完成AOP面向切面編程的實例教程

編輯:關於JAVA

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運用於目的對象上。
  • 創立名為BeforeHandler 和 AfterHandler的兩個aop。前者在辦法履行之前任務,爾後者則在辦法履行停止後任務。
  • 創立一個署理類,使一切的aop handler和目的對象只需作為參數傳入,就可以創立一個hook。
  • 參加你本身的營業邏輯或許橫切存眷點。
  • 最初,經由過程傳入相干的參數創立署理對象(proxy object)。

兩種完成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.................... 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved