代理在java中用多,主要用來對已有功能作擴展和適配。動態代理就涉及到了反射、jvm的類加載機制等信息。通常用在框架中。例如:spring的AOP就是用動態代理。下面作一些簡單講述。
java
a、接口
spring
public interface Count { // 查看帳戶方法 public void queryCount(); // 修改帳戶方法 public void updateCount(); }
b、實現
框架
public class CountImpl implements Count{ @Override public void queryCount() { System.out.println("查看帳戶方法..."); } @Override public void updateCount() { System.out.println("修改帳戶方..."); } }
c、代理類
jvm
public class CountProxy implements Count { private CountImpl countImpl; public CountProxy(CountImpl countImpl) { this.countImpl = countImpl; } @Override public void queryCount() { System.out.println("事務處理以前"); this.countImpl.queryCount(); System.out.println("事物處理以後"); System.out.println(""); } @Override public void updateCount() { System.out.println("事務處理以前"); this.countImpl.updateCount(); System.out.println("事物處理以後"); System.out.println(""); } }
d、測試類
ide
@Test public void staticProxy() { CountProxy cp = new CountProxy(new CountImpl()); cp.updateCount(); cp.queryCount(); }
普通的代理都須要實現但前功能的接口,而後在這個接口上實現一個其它功能。這就會形成在大量功能加強的過程當中,建立不少的proxy類。
測試
動態代經過了JVM的反射和類加載機制,減小了proxy類的建立。咱們只須要建立一個代理類,就能夠在整個項目中使用。this
JDK的動態代理:
spa
JDK的動態代理只能對實現了接口的類來代理,對於沒有實現接口的類不能使用JDK的動態代理。主要分兩部分實現。代理
一、經過:Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);加載咱們須要實現的功能類。code
二、經過下面的接口來操做咱們的方法。:
public interface InvocationHandler { public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; }
例如:a、接口
public interface BookFacade { public void addBook(); }
b、實現類
public class BookFacadeImpl implements BookFacade{ @Override public void addBook() { System.out.println("增長圖書方法..."); } }
c、代理類
public class BookFacadeProxy implements InvocationHandler { private Object target; /** * * @param target * 目標類 * @return 代理的目標類 */ public Object bind(Object target) { this.target = target; // 綁定接口 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * 功能操做 */ @Override public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable { Object result = null; System.out.println("事物開始"); // 執行 result = method.invoke(target, arg2); System.out.println("事物結束"); return result; } }
d、測試
@Test public void dynamicProxy() { BookFacadeProxy bfp = new BookFacadeProxy(); BookFacade bookProxy = (BookFacade) bfp.bind(new BookFacadeImpl()); bookProxy.addBook(); }
CGLIB的動態代理:採用繼承的方式,而後生成子類,並覆蓋。
a、接口
public interface UserDAO { void addUser(); }
b、實現
public class UserDAOImpl implements UserDAO{ @Override public void addUser() { System.out.println("添加了用戶"); } }
c、代理
public class CglibProxy implements MethodInterceptor { private Object target; public Object getInstance(Object target) { this.target = target; Enhancer enhancer = new Enhancer(); // 回調方法 enhancer.setCallback(this); // 建立代理對象 return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("事物開始"); proxy.invokeSuper(obj, args); System.out.println("事物結束"); return null; } }
d、測試
public void cglibProxy() { CglibProxy cp = new CglibProxy(); UserDAO cglibProxy = (UserDAO) cp.getInstance(new UserDAOImpl()); cglibProxy.addUser(); }