運用Java原生代理完成AOP。本站提示廣大學習愛好者:(運用Java原生代理完成AOP)文章只能為提供參考,不一定能成為您想要的結果。以下是運用Java原生代理完成AOP正文
### 本文由博主柒。原創,轉載請注明出處
### 完好源碼下載地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/MatrixSeven/JavaAOP)
一說到AOP,大家一定會想到Spring,由於這東西真實是太弱小了.但是大家一定要清楚,AOP是一只編程思想,而Spring僅僅是AOP的一種完成罷了.
首先百度下:
在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,經過預編譯方式和運轉期靜態代理完成順序功用的一致維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生范型。應用AOP可以對業務邏輯的各個局部停止隔離,從而使得業務邏輯各局部之間的耦合度降低,進步順序的可重用性,同時進步了開發的效率。
假如你對AOP還沒有理解請左移百度百科:[http://baike.baidu.com/search/word?word=AOP](http://baike.baidu.com/search/word?word=AOP檢查)檢查.
明天呢,我們就一同用Java原生代理完成復雜的AOP功用.
首先,你得需求理解根本的反射知識,否則能夠會感到困惑.
不羅嗦了,直接開端撸碼
首先,我們先寫一個復雜的接口.名字叫AnimalInterface,用來聲明標准植物的一些根本辦法.
這些辦法包括 設置名字,獲取名字,叫聲,屬性(原諒我沒文明,其實就是取得是陸棲還是水棲或許水陸兩棲)
```Java
package proxy.imp;
public interface AnimalInterface {
//設置名字
void setName(String name);
//獲取名字
String getName();
//叫聲
void say();
//獲取棲性
void getProperty();
}
```
然後我們完成這個接口,創立一個名叫小黑的Dog
```Java
package proxy;
import proxy.imp.AnimalInterface;
public class DogImp implements AnimalInterface {
private String name = "小黑";
public DogImp() {
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void say() {
System.out.println("小狗:汪汪汪汪.....");
}
@Override
public void getProperty() {
System.out.println("小狗是海洋植物,但是會游泳哦");
}
}
```
大家一定刻不容緩了,怎樣完成相似AOP的功用呢….
我們先創立一個名為AOPHandle的類,讓其完成InvocationHandler接口,
不能運用invoke時運用proxy作為反射參數時,由於代理對象的接口,不同於對象,
這種代理機制是面向接口,而不是面向類的,假如運用proxy,會形成有限遞歸.然後就是棧溢出,但是照舊能反射成功一次,
這闡明代理對象和對象的代理是不一樣的,但是我們可以經過proxy參數的proxy.getClass()取得class對象,然後取得被代理
類的辦法和參數,這也為注解注入,特定辦法注入,屬性注入提供了一種完成途徑吧,關於這個,我們前面再說..
```Java
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class AOPHandle implements InvocationHandler{
//保管對象
private Object o;
public AOPHandle(Object o) {
this.o=o;
}
/**
* 這個辦法會自動調用,Java靜態代理機制
* 會傳入上面是個參數
* @param Object proxy 代理對象的接口,不同於對象
* @param Method method 被調用辦法
* @param Object[] args 辦法參數
* 不能運用invoke時運用proxy作為反射參數時,由於代理對象的接口,不同於對象
* 這種代理機制是面向接口,而不是面向類的
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//辦法前往值
Object ret=null;
//打印辦法稱號
System.err.println("執行辦法:"+method.getName()+"n參數類型為:");
//打印參數
for(Class type:method.getParameterTypes())
System.err.println(type.getName());
//打印前往類型
System.err.println("前往數據類型:"+method.getReturnType().getName());
//反射調用辦法
ret=method.invoke(o, args);
//聲明完畢
System.err.println("辦法執行完畢");
//前往反射調用辦法的前往值
return ret;
}
}
```
靜態代理曾經搞定..然後就是我們的AnimalFactory了..我們持續
```java
package proxy;
import java.lang.reflect.Proxy;
public class AnimalFactory {
/***
* 獲取對象辦法
* @param obj
* @return
*/
private static Object getAnimalBase(Object obj){
//獲取代理對象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new AOPHandle(obj));
}
/***
* 獲取對象辦法
* @param obj
* @return
*/
@SuppressWarnings("unchecked")
public static T getAnimal(Object obj){
return (T) getAnimalBase(obj);
}
/***
* 獲取對象辦法
* @param className
* @return
*/
@SuppressWarnings("unchecked")
public static T getAnimal(String className){
Object obj=null;
try {
obj= getAnimalBase(Class.forName(className).newInstance());
} catch (Exception e) {
e.printStackTrace();
}
return (T)obj;
}
/***
* 獲取對象辦法
* @param clz
* @return
*/
@SuppressWarnings("unchecked")
public static T getAnimal(Class clz){
Object obj=null;
try {
obj= getAnimalBase(clz.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
return (T)obj;
}
}
```
終於到最後了…還差什麼呢,大家來這裡看看效果吧…
哈哈…小二,上個菜..哦~不對,是個測試類..哈哈////
```java
package proxy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.AnimalFactory;
import proxy.imp.AnimalInterface;
@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {
@Test
public void Test1() {
AnimalInterface dog=AnimalFactory.getAnimal(DogImp.class);
dog.say();
System.out.println("我的名字是"+dog.getName());
dog.setName("二狗子");
System.out.println("我的名字是"+dog.getName());
}
}
```
對,我們的效果曾經看到了..
,咦,你會說沒圖沒真相???
好,那就上圖…
```java
圖片在sae上曾經喪失,請大家腦補
```
啥?什麼,,到了最後說,,這又卵用,這不是坑爹麼?就捕捉一個這個玩意,什麼用啊…
什麼AOP,我怎樣一點AOP的影子都沒有看到,怎樣切入自定義辦法,就一個syso輸出,往這忽悠觀眾來了?…..
好吧,那我們持續…看看如何完成注入自定義辦法…
首先添加一個接口,我們就稱為AOP注入接口吧.取名AOPMethod哈
創立after和before辦法,接納Object proxy, Method method, Object[] args參數
這樣就能做更多的事情叻…比方執行辦法前,記載類形態,寫入log.監控xx變量,,,
開啟你的腦洞吧.
```java
package proxy.imp;
import java.lang.reflect.Method;
public interface AOPMethod{
//實例辦法執行前執行的辦法
void after(Object proxy, Method method, Object[] args);
//實例辦法執行後執行的辦法
void before(Object proxy, Method method, Object[] args);
}
```
然後修正AOPHandle類,添加AOPMethod屬性.
在修正結構辦法,讓在類初始化時取得AOPMethod實例.
最後修正invoke辦法….直接上代碼哈
```java
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import proxy.imp.AOPMethod;
public class AOPHandle implements InvocationHandler{
//保管對象
private AOPMethod method;
private Object o;
public AOPHandle(Object o,AOPMethod method) {
this.o=o;
this.method=method;
}
/**
* 這個辦法會自動調用,Java靜態代理機制
* 會傳入上面是個參數
* @param Object proxy 代理對象的接口,不同於對象
* @param Method method 被調用辦法
* @param Object[] args 辦法參數
* 不能運用invoke時運用proxy作為反射參數時,由於代理對象的接口,不同於對象
* 這種代理機制是面向接口,而不是面向類的
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ret=null;
//修正的中央在這裡哦
this.method.before(proxy, method, args);
ret=method.invoke(o, args);
//修正的中央在這裡哦
this.method.after(proxy, method, args);
return ret;
}
}
```
呼呼,半途而廢,,看起來一切都麼問題,萌萌哒..
趕忙更新下測試類…
```java
package proxy;
import java.lang.reflect.Method;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.imp.AOPMethod;
import proxy.imp.AnimalInterface;
@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {
public static void main(String[] args) {
AnimalInterface dog = AnimalFactory.getAnimal(DogImp.class, new AOPMethod() {
// 這裡寫辦法執行前的AOP切入辦法
public void before(Object proxy, Method method, Object[] args) {
System.err.println("我在" + method.getName() + "辦法執行前執行");
}
// 這裡系辦法執行後的AOP切入辦法
public void after(Object proxy, Method method, Object[] args) {
System.err.println("我在 " + method.getName() + "辦法執行後執行");
}
});
dog.say();
String name1="我的名字是" + dog.getName();
System.out.println(name1);
dog.setName("二狗子");
String name2="我的名字是"+dog.getName();
System.out.println(name2);
}
}
```
來個效果圖:
```java
圖片在sae上曾經喪失,請大家腦補
```
呼呼,親們,是不是有注入的覺得了?是不是覺得把自己的辦法切出來了???哈哈….
看起來一切都曾經完滿了,但是總覺得差了點什麼?哦,對,短少了相似於Spring那麼樣的配置文件..
其實那些曾經很復雜了,交給你們去做吧,設計好XML格式化就妥了,等等,你說什麼,還不能阻攔自定義辦法?
不能像Spring那樣阻攔自定義辦法?oh~~NO,其實曾經可以了在
before(Object proxy, Method method, Object[] args)
中應用method和的給methodName就能做判別了.
當然,本例的並沒有什麼適用意義,更不能個各種完善的AOP框架相比,本文僅僅為您提供一種思緒,但是一定要記住,再牛的東西也是一點點積聚出來的
學習理解原理,是為了更好的駕馭所掌握的知識和技藝.咱再會回嘿嘿.