平常開發(fā)中的日志、權(quán)限、事務(wù)處理等。
代理模式實(shí)現(xiàn)原理圖
代理模式:是經(jīng)常使用的java設(shè)計(jì)模式,他的特點(diǎn)是代理類與拜托類有一樣的接口,代理類主要負(fù)責(zé)為拜托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給拜托類,和事后處理消息等。代理類與拜托類之間通常會(huì)存在關(guān)聯(lián)關(guān)系,1個(gè)代理類的對(duì)象與1個(gè)拜托類的對(duì)象關(guān)聯(lián),代理類的對(duì)象本身其實(shí)不真正實(shí)現(xiàn)服務(wù),而是通過調(diào)用拜托類的對(duì)象的相干方法,來提供特定的服務(wù)。
依照代理的創(chuàng)建時(shí)期,代理類可以分為兩種。
靜態(tài)代理:由程序員創(chuàng)建或特定工具自動(dòng)生成源代碼,再對(duì)其編譯。在程序運(yùn)行前,代理類的.class文件就已存在了。
動(dòng)態(tài)代理:在程序運(yùn)行時(shí),應(yīng)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成。
1.抽象目標(biāo)類
public interface Subject(){
public void Request();
}
2.具體目標(biāo)類
public class RealSubject implements Subject(){
public void Request(){
};
}
3.代理類
public class Proxy (){
private RealSubject realSubject;
public void Request(){
/**附加邏輯**/
realSubject.Request();
/**附加邏輯**/
};
}
JDK動(dòng)態(tài)的代理的3個(gè)主要類:
Proxy:代理類
InvocationHandler: 接口
Method:要被調(diào)用的方法
TaxInterface.java
public interface TaxInterface {
public void doTax();
}
Tax.java
public class Tax implements TaxInterface{
@Override
public void doTax() {
System.out.println("進(jìn)行所得稅計(jì)算的邏輯處理");
}
}
TimeProxy.java
public class TimeProxy implements InvocationHandler{
private Object obj;
//綁定代理對(duì)象
public Object bind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
//實(shí)現(xiàn)代理
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
try {
long startTime = System.nanoTime();
result = method.invoke(obj, args);
long endTime = System.nanoTime();
System.out.println("計(jì)算程序運(yùn)行時(shí)間 :" +(endTime-startTime));
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
客戶端測(cè)試:Client.java
public class Client {
public static void main(String[] args) {
TimeProxy timeProxy = new TimeProxy();
TaxInterface taxInterface = (TaxInterface)timeProxy.bind(new Tax());
taxInterface.doTax();
}
}
JDK的動(dòng)態(tài)代理依托接口實(shí)現(xiàn),如果有些類并沒有實(shí)現(xiàn)接口,則不能使用JDK代理,這就要使用cglib動(dòng)態(tài)代理了。
JDK的動(dòng)態(tài)代理機(jī)制只能代理實(shí)現(xiàn)了接口的類,而不能實(shí)現(xiàn)接口的類就不能實(shí)現(xiàn)JDK的動(dòng)態(tài)代理,cglib是針對(duì)類來實(shí)現(xiàn)代理的,他的原理是對(duì)指定的目標(biāo)類生成1個(gè)子類,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但由于采取的是繼承,所以不能對(duì)final修飾的類進(jìn)行代理。
示例以下:
BookFacadeCglib.java
package com.ldw.dao;
public interface BookFacade {
public void addBook();
}
BookCadeImpl1.java
package com.ldw.dao.impl;
/**
* 這個(gè)是沒有實(shí)現(xiàn)接口的實(shí)現(xiàn)類
*
* @author csu.ldw
*
*/
public class BookFacadeImpl1 {
public void addBook() {
System.out.println("增加圖書的普通方法...");
}
}
BookFacadeProxy.java
package com.ldw.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 使用cglib動(dòng)態(tài)代理
*
* @author student
*
*/
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
/**
* 創(chuàng)建代理對(duì)象
*
* @param target
* @return
*/
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回調(diào)方法
enhancer.setCallback(this);
// 創(chuàng)建代理對(duì)象
return enhancer.create();
}
@Override
// 回調(diào)方法
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("事物開始");
proxy.invokeSuper(obj, args);
System.out.println("事物結(jié)束");
return null;
}
}
TestCglib.java
package com.ldw.test;
import net.battier.dao.impl.BookFacadeImpl1;
import net.battier.proxy.BookFacadeCglib;
public class TestCglib {
public static void main(String[] args) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}
SpringAOP、Struts攔截器、日志管理等。
struts2的攔截器屬于AOP思想,采取了代理模式
struts2中,最重要的1個(gè)類是org.apache.struts2.dispatcher.FilterDispatcher用戶通過閱讀器提交1個(gè)HttpServletRequest要求后,要求被在web.xml中的過濾器FilterDispatcher攔截在FilterDispatcher過濾器中首先詢問ActionMapper是不是需要調(diào)用某個(gè)Action來處理要求,如果ActionMapper決定需要調(diào)用某個(gè)要求,F(xiàn)ilterDispatcher則把要求的處理交給ActionProxy,ActionProxy通過配置文件struts.xml找到需要調(diào)用的Action類,然后ActionProxy創(chuàng)建1個(gè)ActionInvocation實(shí)例并通用該Action但在調(diào)用之前,ActionInvocation會(huì)根據(jù)配置加載Action相干的Intercepter,等Action履行終了,ActionInvocation負(fù)責(zé)根據(jù)struts.xml中的配置找到對(duì)應(yīng)的Result結(jié)果。