newProxyInstance()方法介紹
Proxy類的newInstance()方法有三個引數:
ClassLoader loader:它是類載入器型別,你不用去理睬它,你只需要知道怎麼可以獲得它就可以了:MyInterface.class.getClassLoader()就可以獲取到ClassLoader物件,沒錯,只要你有一個Class物件就可以獲取到ClassLoader物件;Class[] interfaces:指定newProxyInstance()方法返回的物件要實現哪些介面,沒錯,可以指定多個介面,例如上面例子只我們只指定了一個介面:Class[] cs = {MyInterface.class};InvocationHandler h:它是最重要的一個引數!它是一個介面!它的名字叫呼叫處理器!無論你呼叫代理物件的什麼方法,它都是在呼叫InvocationHandler的invoke()方法!
AOP介紹
Aspect Oriented Programming(AOP)是較為熱門的一個話題。AOP,國內大致譯作“面向切面程式設計”。
- “面向切面程式設計”,這樣的名字並不是非常容易理解,且容易產生一些誤導。
- 筆者不止一次聽到類似“OOP/OOD11即將落伍,AOP是新一代軟體開發方式”這樣的發言。而在AOP中,Aspect的含義,可能更多的理解為“切面”比較合適。所以筆者更傾向於“面向切面程式設計”的譯法。可以通過預編譯方式和執行期動態代理實現在不修改原始碼的情況下給程式動態統一新增功能的一種技術。
- AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是呼叫者和被呼叫者之間的解耦,提高程式碼的靈活性和可擴充套件性,AOP可以說也是這種目標的一種實現。
應用物件只實現它們應該做的——完成業務邏輯——僅此而已。它們並不負責(甚至是意識)其它的系統級關注點,例如日誌或事務支援。
AOP主要功能
日誌記錄,效能統計,安全控制,事務處理,異常處理等等wn及擴充套件
AOP主要意圖
將日誌記錄,效能統計,安全控制,事務處理,異常處理等程式碼從業務邏輯程式碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的程式碼。
AOP實現
package org.java.base.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MainApp1 {
public static void main(String[] args) {
ClassLoader loader = MainApp1.class.getClassLoader();
Class[] cs = {Waiter.class};
Waiter target = new MyWaiter();
MyInvocationHandler h = new MyInvocationHandler(target);
Waiter waiter = (Waiter)Proxy.newProxyInstance(loader, cs, h);
waiter.serve();
}
}
class MyInvocationHandler implements InvocationHandler {
public Waiter target;
public MyInvocationHandler(Waiter target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
System.out.println("您好!");
Object result = method.invoke(target, args);
System.out.println("很高興為您服務!");
return result;
}
}複製程式碼
package org.java.base.proxy;
/**
* 後置增強
* @author Liuhaihua
*
*/
public interface AfterAdvice {
public void after();
}複製程式碼
package org.java.base.proxy;
/**
* 前置增強
* @author Liuhaihua
*
*/
public interface BeforeAdvice {
public void before();
}
複製程式碼
package org.java.base.proxy;
public class MyWaiter implements Waiter {
public void serve() {
System.out.println("服務...");
}
}複製程式碼
package org.java.base.proxy;
public interface Waiter {
// 服務
public void serve();
}複製程式碼
package org.java.base.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 它用來生成代理物件
* 它需要所有的引數
* * 目標物件
* * 增強
* @author cxf
*/
/**
* 1. 建立代理工廠
* 2. 給工廠設定三樣東西:
* * 目標物件:setTargetObject(xxx);
* * 前置增強:setBeforeAdvice(該介面的實現)
* * 後置增強:setAfterAdvice(該介面的實現)
* 3. 呼叫createProxy()得到代理物件
* * 執行代理物件方法時:
* > 執行BeforeAdvice的before()
* > 目標物件的目標方法
* > 執行AfterAdvice的after()
* @author cxf
*
*/
public class ProxyFactory {
private Object targetObject;//目標物件
private BeforeAdvice beforeAdvice;//前置增強
private AfterAdvice afterAdvice;//後置增強
/**
* 用來生成代理物件
* @return
*/
public Object createProxy() {
/*
* 1. 給出三大引數
*/
ClassLoader loader = this.getClass().getClassLoader();
Class[] interfaces = targetObject.getClass().getInterfaces();
InvocationHandler h = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/*
* 在呼叫代理物件的方法時會執行這裡的內容
*/
// 執行前置增強
if(beforeAdvice != null) {
beforeAdvice.before();
}
Object result = method.invoke(targetObject, args);//執行目標物件的目標方法
// 執行後置增強
if(afterAdvice != null) {
afterAdvice.after();
}
// 返回目標物件的返回值
return result;
}
};
/*
* 2. 得到代理物件
*/
Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
return proxyObject;
}
public Object getTargetObject() {
return targetObject;
}
public void setTargetObject(Object targetObject) {
this.targetObject = targetObject;
}
public BeforeAdvice getBeforeAdvice() {
return beforeAdvice;
}
public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
this.beforeAdvice = beforeAdvice;
}
public AfterAdvice getAfterAdvice() {
return afterAdvice;
}
public void setAfterAdvice(AfterAdvice afterAdvice) {
this.afterAdvice = afterAdvice;
}
}
複製程式碼
程式碼下載:gitee.com/jxuasea/max…