代理在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(); }