代理機制
Java動態代理機制的出現,使得Java開發人員不用手工編寫代理類,只要簡單地制定一組介面及委託類對象,便能動態地獲得代理類。代理類會負責將所有的方法調用分配到委託對象上反射執行,配置執行過程中,開發人員還可以進行修改
代理設計模式
代理是一種常用的設計模式,其目的就是為其他對象提供一個代理以控制對某個對象的訪問。代理類負責為委託類預處理消息、過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。
為了保持行為的一致性,代理類和委託類通常會實現相同的介面
2. 引入代理能夠控制對委託對象的直接訪問,可以很好的隱藏和保護委託對象,也更加具有靈活性
代理機制及其特點
首先讓我們來了解一下如何使用 Java 動態代理。具體有如下四步驟:
通過實現 InvocationHandler 介面創建自己的調用處理器;
通過為 Proxy 類指定 ClassLoader 對象和一組 interface 來創建動態代理類;
通過反射機制獲得動態代理類的構造函數,其唯一參數類型是調用處理器介面類型;
通過構造函數創建動態代理類實例,構造時調用處理器對象作為參數被傳入。
代理類實例的一些特點
每個實例都會關聯一個InvocationHandler(調用處理器對象),在代理類實例上調用其代理介面中聲明的方法時,最終都會由InvocationHandler的invoke方法執行;
java.lang.Object中有三個方法也同樣會被分派到調用處理器的 invoke 方法執行,它們是 hashCode,equals 和 toString;
代碼示例
最後以一個簡單的動態代理例子結束
⑵ 如何使用Proxy模式及Java內建的動態代理機制
在學習Spring的時候,我們知道Spring主要有兩大思想,一個是IoC,另一個就是AOP,對於IoC,依賴注入就不用多說了,而對於Spring的核心AOP來說,我們不但要知道怎麼通過AOP來滿足的我們的功能,我們更需要學習的是其底層是怎麼樣的一個原理,而AOP的原理就是java的動態代理機制,所以本篇隨筆就是對java的動態機制進行一個回顧。
在java的動態代理機制中,有兩個重要的類或介面,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class),這一個類和介面是實現我們動態代理所必須用到的。首先我們先來看看java的API幫助文檔是怎麼樣對這兩個類進行描述的:
InvocationHandler:
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
每一個動態代理類都必須要實現InvocationHandler這個介面,並且每個代理類的實例都關聯到了一個handler,當我們通過代理對象調用一個方法的時候,這個方法的調用就會被轉發為由InvocationHandler這個介面的 invoke 方法來進行調用。我們來看看InvocationHandler這個介面的唯一一個方法 invoke 方法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
我們看到這個方法一共接受三個參數,那麼這三個參數分別代表什麼呢?
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
proxy:指代我們所代理的那個真實對象
method:指代的是我們所要調用真實對象的某個方法的Method對象
args:指代的是調用真實對象某個方法時接受的參數
如果不是很明白,等下通過一個實例會對這幾個參數進行更深的講解。
接下來我們來看看Proxy這個類:
Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
Proxy這個類的作用就是用來動態創建一個代理對象的類,它提供了許多的方法,但是我們用的最多的就是 newProxyInstance 這個方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
這個方法的作用就是得到一個動態的代理對象,其接收三個參數,我們來看看這三個參數所代表的含義:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
loader:一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行載入
interfaces:一個Interface對象的數組,表示的是我將要給我需要代理的對象提供一組什麼介面,如果我提供了一組介面給它,那麼這個代理對象就宣稱實現了該介面(多態),這樣我就能調用這組介面中的方法了
h:一個InvocationHandler對象,表示的是當我這個動態代理對象在調用方法的時候,會關聯到哪一個InvocationHandler對象上
好了,在介紹完這兩個介面(類)以後,我們來通過一個實例來看看我們的動態代理模式是什麼樣的:
首先我們定義了一個Subject類型的介面,為其聲明了兩個方法:
public interface Subject
{
public void rent();
public void hello(String str);
}
接著,定義了一個類來實現這個介面,這個類就是我們的真實對象,RealSubject類:
public class RealSubject implements Subject
{
@Override
public void rent()
{
System.out.println("I want to rent my house");
}
@Override
public void hello(String str)
{
System.out.println("hello: " + str);
}
}
下一步,我們就要定義一個動態代理類了,前面說個,每一個動態代理類都必須要實現 InvocationHandler 這個介面,因此我們這個動態代理類也不例外:
public class DynamicProxy implements InvocationHandler
{
//這個就是我們要代理的真實對象
private Object subject;
// 構造方法,給我們要代理的真實對象賦初值
public DynamicProxy(Object subject)
{
this.subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真實對象前我們可以添加一些自己的操作
System.out.println("before rent house");
System.out.println("Method:" + method);
// 當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用
method.invoke(subject, args);
//在代理真實對象後我們也可以添加一些自己的操作
System.out.println("after rent house");
return null;
}
}
最後,來看看我們的Client類:
public class Client
{
public static void main(String[] args)
{
// 我們要代理的真實對象
Subject realSubject = new RealSubject();
// 我們要代理哪個真實對象,就將該對象傳進去,最後是通過該真實對象來調用其方法的
InvocationHandler handler = new DynamicProxy(realSubject);
/*
* 通過Proxy的newProxyInstance方法來創建我們的代理對象,我們來看看其三個參數
* 第一個參數 handler.getClass().getClassLoader() ,我們這里使用handler這個類的ClassLoader對象來載入我們的代理對象
* 第二個參數realSubject.getClass().getInterfaces(),我們這里為代理對象提供的介面是真實對象所實行的介面,表示我要代理的是該真實對象,這樣我就能調用這組介面中的方法了
* 第三個參數handler, 我們這里將這個代理對象關聯到了上方的 InvocationHandler 這個對象上
*/
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
}
我們先來看看控制台的輸出:
$Proxy0
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
I want to rent my house
after rent house
before rent house
Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
hello: world
after rent house
我們首先來看看 $Proxy0 這東西,我們看到,這個東西是由 System.out.println(subject.getClass().getName()); 這條語句列印出來的,那麼為什麼我們返回的這個代理對象的類名是這樣的呢?
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
可能我以為返回的這個代理對象會是Subject類型的對象,或者是InvocationHandler的對象,結果卻不是,首先我們解釋一下為什麼我們這里可以將其轉化為Subject類型的對象?原因就是在newProxyInstance這個方法的第二個參數上,我們給這個代理對象提供了一組什麼介面,那麼我這個代理對象就會實現了這組介面,這個時候我們當然可以將這個代理對象強制類型轉化為這組介面中的任意一個,因為這里的介面是Subject類型,所以就可以將其轉化為Subject類型了。
同時我們一定要記住,通過 Proxy.newProxyInstance 創建的代理對象是在jvm運行時動態生成的一個對象,它並不是我們的InvocationHandler類型,也不是我們定義的那組介面的類型,而是在運行是動態生成的一個對象,並且命名方式都是這樣的形式,以$開頭,proxy為中,最後一個數字表示對象的標號。
接著我們來看看這兩句
subject.rent();
subject.hello("world");
這里是通過代理對象來調用實現的那種介面中的方法,這個時候程序就會跳轉到由這個代理對象關聯到的 handler 中的invoke方法去執行,而我們的這個 handler 對象又接受了一個 RealSubject類型的參數,表示我要代理的就是這個真實對象,所以此時就會調用 handler 中的invoke方法去執行:
public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//在代理真實對象前我們可以添加一些自己的操作
System.out.println("before rent house");
System.out.println("Method:" + method);
// 當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用
method.invoke(subject, args);
//在代理真實對象後我們也可以添加一些自己的操作
System.out.println("after rent house");
return null;
}
我們看到,在真正通過代理對象來調用真實對象的方法的時候,我們可以在該方法前後添加自己的一些操作,同時我們看到我們的這個 method 對象是這樣的:
public abstract void com.xiaoluo.dynamicproxy.Subject.rent()
public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)
正好就是我們的Subject介面中的兩個方法,這也就證明了當我通過代理對象來調用方法的時候,起實際就是委託由其關聯到的 handler 對象的invoke方法中來調用,並不是自己來真實調用,而是通過代理的方式來調用的。
這就是我們的java動態代理機制
⑶ 怎麼制定一個合理的代理機制,需要遵循什麼原則
最起碼你在制定機制之前,要考慮自己的產品出廠價格是多少,自己零售價打算賣多少,給自己預留的利潤是多少。如果你還是不清楚的話可以去找微一案詢問他們的建議,需要考慮到哪些你沒有考慮到的因素。
⑷ java動態代理機制
在目前的Java開發包中包含了對動態代理的支持,但是其實現只支持對介面的的實現。
其實現主要通過是java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler介面。
Proxy類主要用來獲取動態代理對象,InvocationHandler介面用來約束調用者實現,如下,HelloWorld介面定義的業務方法,HelloWorldImpl是HelloWorld介面的實現,HelloWorldHandler是 InvocationHandler介面實現。代碼如下:
業務介面:
public interface HelloWorld {
void sayHelloWorld() ;
}
業務介面實現:
public class HelloWorldImpl implements HelloWorld {
public void sayHelloWorld() {
System.out.println("Hello World!");
}
}
InvocationHandler實現,需要在介面方法調用前後加入一部份處理工作,這里僅僅在方法調用前後向後台輸出兩句字元串,其代碼如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class HelloWorldHandler implements InvocationHandler {
//要代理的原始對象
private Object objOriginal;
/**
* 構造函數。
* @param obj 要代理的原始對象。
*/
public HelloWorldHandler(Object obj) {
this.objOriginal = obj ;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result ;
//方法調用之前
doBefore();
//調用原始對象的方法
result = method.invoke(this.objOriginal ,args);
//方法調用之後
doAfter();
return result ;
}
private void doBefore() {
System.out.println("before method invoke!");
}
private void doAfter() {
System.out.println("after method invoke!");
}
}
測試代碼:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
HelloWorld hw = new HelloWorldImpl();
InvocationHandler handler = new HelloWorldHandler(hw);
HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(
hw.getClass().getClassLoader(),
hw.getClass().getInterfaces(),
handler);
proxy.sayHelloWorld();
}
}
Ø 首先獲取一個業務介面的實現對象;
Ø 獲取一個InvocationHandler實現,此處是HelloWorldHandler對象;
Ø 創建動態代理對象;
Ø 通過動態代理對象調用sayHelloWorld()方法,此時會在原始對象HelloWorldImpl. sayHelloWorld()方法前後輸出兩句字元串。
運行測試類輸出如下:
before method invoke!
Hello World!
after method invoke!
此處Test類中的方法調用代碼比較多,在我們的實際應用中可以通過配置文件來來簡化客戶端的調用實現。另外也可以通過動態代理來實現簡單的AOP。
⑸ java什麼是動態代理機制,謝謝!
這個講的比較詳細。我這里就不內多說了。容
http://blog.csdn.net/u012685794/article/details/53914697
⑹ 如何使用Proxy模式及Java內建的動態代理機制
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyMain {
public static void main(String[] args) {
Service service = new ServiceImpl();
Service proxy = (Service) Proxy.newProxyInstance(service.getClass().getClassLoader(),
service.getClass().getInterfaces(), new ServiceInvocationHandler(service));
System.out.println(proxy.sayHi("Arvin"));
}
}
class ServiceInvocationHandler implements InvocationHandler {
private final Service target;
public ServiceInvocationHandler(Service target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(target, args);
}
}
interface Service {
String sayHi(String name);
}
class ServiceImpl implements Service {
@Override
public String sayHi(String name) {
return "Hi, " + name;
}
}
⑺ spring中aop的動態代理機制有哪些
1.事務管理: (1)資料庫事務:(2)編程事務(3)聲明事物:Spring AOP-->聲明事物
2.日誌處理:
3.安全驗證: Spring AOP---OOP升級
靜態代理原理:目標對象:調用業務邏輯 代理對象:日誌管理
表示層調用--->代理對象(日誌管理)-->調用目標對象
動態代理原理:spring AOP採用動態代理來實現
(1)實現InvocationHandler介面
(2)創建代理類(通過java API)
⑻ 保險代理機制的優缺點
最大的優點是保險公司的經營成本下降,簽訂的是代理合同,不用給代理人購買五險一金,一旦代理人違規,直接取消其代理資格,把責任推給代理人,與公司無關。
最大的缺點是代理人無歸屬感,流動性巨大,流失性也巨大,保險代理人從一個公司跳到另一個公司非常頻繁,就是經理級的也經常在各個公司跳來跳去,同時全國2000多萬考過代理人資格證的,現在只有300萬人在干,浪費巨大。
⑼ 年輕態的代理機制怎麼樣
年輕態的代理機制透明,級別簡單,而且還有眾多不定時額外獎勵。關注年輕態官方工重號參考
⑽ 如何設計委託代理關系的激勵機制
通過分析委託代理關系中存在的委託人與代理人之間信息不對稱、責任不對稱、目標函數不一致等弊端,揭示了委託代理關系的核心問題是代理人的道德風險問題.由於代理人道德風險問題的解決主要依賴於設計合適有效的激勵機制,文章在回顧信息經濟學中顯性激勵機制理論、隱性激勵機制理論、錦標制度理論和自我強迫實現機制理論的基礎上,提出了委託代理關系中激勵機制設計的基本思路.
出版源
《華南理工大學學