java靜態代理與動態代理理解
阿新 • • 發佈:2018-12-13
#1.靜態代理
其實就是一個典型的代理模式實現,在代理類中包裝一個被代理物件,然後影響被代理物件的行為
程式碼示例:
// 介面 public interface Hello { public void sayHello(String name); } // 實現類 @Slf4j public class HelloImpl implements Hello { @Override public void sayHello(String name) { // log.info("----->HelloImpl:{}", name); System.out.println(">>>>>:HelloImpl" + name); } } /** * @Auther: 18030501 * @Date: 2018/10/15 16:51 * @Description: 代理類 */ @Slf4j public class HelloProxy implements Hello { private Hello hello; public HelloProxy(Hello hello) { this.hello = hello; } @Override public void sayHello(String name) { log.info("do sayHello before..."); hello.sayHello(name); log.info("do sayHello after..."); } } /** * @Auther: 18030501 * @Date: 2018/10/15 16:56 * @Description: 靜態代理測試 */ public class TestHelloProxy { public static void main(String[] args) { Hello hello =new HelloProxy(new HelloImpl()); hello.sayHello("李峰"); } }
執行結果:
#2.動態代理
分類:JDK動態代理與CGLIB動態代理
####JDK動態代理:
此時代理物件和目標物件實現了相同的介面,目標物件作為代理物件的一個屬性,具體介面實現中,可以在呼叫目標物件相應方法前後加上其他業務處理邏輯。
代理模式在實際使用時需要指定具體的目標物件,如果為每個類都新增一個代理類的話,會導致類很多,同時如果不知道具體類的話,怎樣實現代理模式呢?這就引出動態代理。JDK動態代理只能針對實現了介面的類生成代理!
程式碼示例:
/** * @Auther: 18030501 * @Date: 2018/10/15 17:23 * @Description: 介面 */ public interface UserService { public abstract void login(String name); void logout(String name); } /** * @Auther: 18030501 * @Date: 2018/10/15 17:23 * @Description: 實現類 */ @Slf4j public class UserServiceImpl implements UserService { @Override public void login(String name) { log.info("{} login...", name); } @Override public void logout(String name) { log.info("{} logout...", name); } } /** * @Auther: 18030501 * @Date: 2018/10/15 17:24 * @Description: 增強的類 */ @Slf4j public class UserServiceHandler implements InvocationHandler { private UserService userService; public UserServiceHandler(UserService userService) { this.userService = userService; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 執行前可以做點什麼 log.info("before do method..."); // 執行被代理類的方法 Object obj = method.invoke(userService, args); // 執行後可以做點什麼 log.info("after do method..."); return obj; } } /** * @Auther: 18030501 * @Date: 2018/10/15 17:27 * @Description: JDK動態代理 */ public class ProxyFactory { public static void main(String[] args) throws Exception { UserService userService = new UserServiceImpl(); UserService obj = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new UserServiceHandler(userService)); obj.login("拿著核武器的程式設計師"); // 輸出代理類的class檔案 // byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{userService.getClass()}); // FileOutputStream os = new FileOutputStream("Proxy0.class"); // os.write(bytes); // os.flush(); // os.close(); // obj.logout(); // userService.logout(); }
執行結果:
####CGLIB動態代理:
CGLIB代理是針對類實現代理,
主要是對指定的類生成一個子類,覆蓋其中的所有方法,使用的是繼承的方式,所以該類或方法不能宣告稱final的。
CGLib是一個強大、高效能的Code生產類庫,可以實現執行期動態擴充套件java類,Spring在執行期間通過
CGlib繼承要被動態代理的類,重寫父類的方法,實現AOP面向切面程式設計
程式碼示例:
/** * @Auther: 18030501 * @Date: 2018/10/15 19:08 * @Description: CGLIB動態代理 */ @Slf4j public class ProxyFactory2 implements MethodInterceptor { public static void main(String[] args) { UserService userService = new UserServiceImpl(); ProxyFactory2 proxyFactory2 = new ProxyFactory2(); UserService proxyObject = proxyFactory2.getProxyObject(userService.getClass()); proxyObject.login("拿著核武器的程式設計師"); } // 提供對應的增強操作類 private Enhancer enhancer = new Enhancer(); public UserService getProxyObject(Class clazz) { // 設定所要增強的類的父類 enhancer.setSuperclass(clazz); // 設定回撥物件 enhancer.setCallback(this); // 建立對應的物件 return (UserService) enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { log.info("do before...."); // 這裡需要注意,由於methodProxy物件是增強後的Method物件,所以這裡需要呼叫的 // 是methodProxy父類的方法,也就是所要增強的類的方法,以實現原來的功能 Object obj = methodProxy.invokeSuper(o, objects); log.info("do after...."); return obj; } }
執行結果:
##JDK動態代理與CGLIB動態代理的區別:
1.JDK針對介面的類實現代理,CGLIB針對類實現代理
2.JDK代理的方式是生產介面實現類的兄弟類用來完成代理,
CGLIB代理的方式通過繼承被代理類的方式完成的代理。