JAVA基礎(一)——代理模式
阿新 • • 發佈:2017-12-23
throws tle ddb 加載 dynamic pro return 描述 類加載
實現java代理一般分為靜態代理和動態代理(jdk代理和cglib代理)
代理模式
簡單的說就是對原有的業務進行代理,外界通過代理訪問真實對象,代理類似現在的中介機構,房產中介就是一個代理,代理房東,租戶只要找到代理而無須關心房東是誰,代理能在房東的基礎上增強房東的行為。
代理模式代碼
JAVA靜態代理
業務接口
package com.rrg.proxy.jdk.staticProxy; /** * * @author abc * */ public interface Count { /** * 查詢余額 */ public void queryMoney();/** * 轉賬 */ public void transferMoney(); }
業務實現類
package com.rrg.proxy.jdk.staticProxy; public class CountImpl implements Count { public void queryMoney() { System.out.println("queryMoney()"); } public void transferMoney() { System.out.println("transferMoney()"); } }
代理
package com.rrg.proxy.jdk.staticProxy; /** * java靜態代理 * @author abc * */ public class JDKStaticProxy implements Count { private CountImpl countImpl; public JDKStaticProxy(CountImpl countImpl) { this.countImpl = countImpl; } public void queryMoney() { System.out.println("===開始查詢==="); countImpl.queryMoney(); System.out.println("===查詢結束==="); } public void transferMoney() { System.out.println("===開始轉賬==="); countImpl.transferMoney(); System.out.println("===轉賬成功==="); } }
測試
/** * jdk靜態代理 */ @Test public void test1(){ CountImpl impl = new CountImpl(); JDKStaticProxy proxy = new JDKStaticProxy(impl); proxy.queryMoney(); System.out.println(); proxy.transferMoney(); }
JAVA動態代理
模擬業務方法接口UserService.java
package com.rrg.proxy.jdk.dynamic;
/**
* 創建業務接口
* @author abc
*
*/
public interface UserService {
/**
* 新增人員
*/
public void add();
}
業務方法實現UserServiceImpl.java
package com.rrg.proxy.jdk.dynamic;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("add()");
}
}
代理類,負責處理代理
package com.rrg.proxy.jdk.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JDKDynamicHandler implements InvocationHandler { private UserService userService; public JDKDynamicHandler(UserService userService) { super(); this.userService = userService; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("===添加人員處理==="); Object result = method.invoke(userService, args); System.out.println("===添加人員完畢==="); return result; } public Object getProxy() { //通過反射機制,創建一個代理類對象實例並返回。用戶進行方法調用時使用 //創建代理對象時,需要傳遞該業務類的類加載器(用來獲取業務實現類的元數據,在包裝方法是調用真正的業務方法)、接口、handler實現類 return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), this.userService.getClass().getInterfaces(), this); } }
測試
/** * jdk動態代理 */ @Test public void test2() { UserService userService = new UserServiceImpl(); JDKDynamicHandler handler = new JDKDynamicHandler(userService); UserService proxy = (UserService) handler.getProxy(); proxy.add(); }
CGLIB動態代理
不需要接口直接代理實現類
業務實現類
package com.rrg.proxy.cglib; public class BookFacadeImpl { /** * 添加圖書 */ public void addBook() { System.out.println("addBook()"); } }
代理
package com.rrg.proxy.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class BookFacadeCglib implements MethodInterceptor { private BookFacadeImpl bookService; public Object getInstance(BookFacadeImpl bookService) { Enhancer enhancer = new Enhancer(); //創建加強器,用來創建動態代理類 enhancer.setSuperclass(this.bookService.getClass()); //為加強器指定要代理的業務類(即:為下面生成的代理類指定父類) //設置回調:對於代理類上所有方法的調用,都會調用CallBack,而Callback則需要實現intercept()方法進行攔 enhancer.setCallback(this); // 創建動態代理類對象並返回 return enhancer.create(); } //回調方法 public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("===準備添加圖書==="); methodProxy.invokeSuper(object, args); System.out.println("===完成添加圖書==="); return null; } }
測試
/** * cglib動態代理 */ @Test public void test3() { BookFacadeImpl bookService = new BookFacadeImpl(); BookFacadeCglib cglib = new BookFacadeCglib(); BookFacadeImpl bookCglib = (BookFacadeImpl) cglib.getInstance(bookService); bookCglib.addBook(); }
總結
(1)靜態代理是在編譯時創建一個業務代理類,通過代理訪問同名方法,實現對原方法的包裝(代理類繼承業務類)
(2)JDK動態代理通過接口的方法名,在動態的代理類調用同名業務方法,實現對原方法的包裝(實現InvocationHandler)
(3)CGLIB動態代理通過繼承業務類,創建出一個增強的業務類(實現MethodInterceptor)
代理是一個AOP思想的體現,切面編程對業務方法的前後進行增強
在Spring的AOP編程中:
如果加入容器的目標對象有實現接口,用JDK代理
如果目標對象沒有實現接口,用Cglib代理
JAVA基礎(一)——代理模式