标签:style blog io 使用 java ar for 数据 2014
关于动态代理,大家显式使用的可能比较少,但是说到Spring的Interceptor、各种各样的事务管理,大家会更熟悉一些,没错,这些在底层实现上,都是使用的动态代理,确切的说,想要为一个类的方法,动态添加功能,比如验证、资源释放、日志处理等,大部分都是借助动态代理。
为了平缓的过渡,先来说一下静态代理。
静态代理的思路很简单:把一个真实对象的实例放到代理对象的实例中,然后调用代理对象方法,代理对象的方法调用真实对象的方法,以事务管理为例,如下:
package com.tgb.staticproxy; public interface UserDao { public void add(); public void deleteAll(); }
package com.tgb.staticproxy; public class UserDaoImpl implements UserDao { public void add() { System.out.println("添加一名用户到数据库"); } public void deleteAll() { System.out.println("删除所有用户"); } }
package com.tgb.staticproxy; public class UserDaoProxy implements UserDao { UserDao userDao=null; public UserDaoProxy(UserDao userDao) { this.userDao=userDao; } public void add() { System.out.println("开启本地事务"); userDao.add(); System.out.println("提交或回滚事务"); } public void deleteAll() { System.out.println("开启本地事务"); userDao.deleteAll(); System.out.println("提交或回滚事务"); } }
package com.tgb.staticproxy; public class Test { /** * @param args */ public static void main(String[] args) { UserDao userDao=new UserDaoImpl(); UserDaoProxy userDaoProxy=new UserDaoProxy(userDao); //测试添加 userDaoProxy.add(); System.out.println("..........分隔符.........."); //测试删除 userDaoProxy.deleteAll(); } }
开启本地事务 添加一名用户到数据库 提交或回滚事务 ..........分隔符.......... 开启本地事务 删除所有用户 提交或回滚事务
同样以事务管理为例,如下:
package com.tgb.dynamicproxy; public interface UserDao { public void add(); public void deleteAll(); }
package com.tgb.dynamicproxy; public class UserDaoImpl implements UserDao { @Override public void deleteAll() { System.out.println("删除所有用户信息"); } @Override public void add() { System.out.println("添加一名用户到数据库"); } }
package com.tgb.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class Handler implements InvocationHandler { private Object target; public Handler(Object target) { this.target=target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //开启事务 before(); //执行业务 method.invoke(target, args); //提交或回滚事务 after(); return null; } public void before() { System.out.println("开始本地事务"); } public void after() { System.out.println("提交或回滚事务"); } }
package com.tgb.dynamicproxy; import java.lang.reflect.Proxy; public class Test { /** * @param args */ public static void main(String[] args) { try{ UserDao impl=new UserDaoImpl(); Handler handler=new Handler(impl); UserDao proxy=(UserDao)Proxy.newProxyInstance (impl.getClass().getClassLoader(), impl.getClass().getInterfaces(), handler); //测试添加 proxy.add(); System.out.println("..........分隔符.........."); //测试删除 proxy.deleteAll(); } catch(Exception e) { e.printStackTrace(); } } }
开始本地事务 添加一名用户到数据库 提交或回滚事务 ..........分隔符.......... 开始本地事务 删除所有用户信息 提交或回滚事务
JDK的动态代理克服了静态代理耦合和代码重复的问题,但是JDK的代理模式有个比较严重的问题,如UserDao必须要有接口才可以使用JDK动态代理,这就大大限制了JDK动态代理的范围。
package com.tgb.cglib; public class UserDaoImpl { public void deleteAll() { System.out.println("删除所有用户信息"); } public void add() { System.out.println("添加一名用户到数据库"); } }
package com.tgb.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { private Object target; private CglibProxy(Object target){ this.target = target; } //产生代理对象 @SuppressWarnings("unchecked") public static <T> T proxyTarget(T t){ Enhancer en = new Enhancer(); en.setSuperclass(t.getClass()); en.setCallback((Callback) new CglibProxy(t)); T tt = (T) en.create(); return tt; } //执行拦截 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开启本地事务"); Object o = method.invoke(target, args); System.out.println("提交或回滚事务"); return o; } }
package com.tgb.cglib; public class Test { /** * @param args */ public static void main(String[] args) { //获取代理对象 UserDaoImpl impl=CglibProxy.proxyTarget(new UserDaoImpl()); //测试添加 impl.add(); System.out.println("..........分隔符.........."); //测试删除 impl.deleteAll(); } }
开启本地事务 添加一名用户到数据库 提交或回滚事务 ..........分隔符.......... 开启本地事务 删除所有用户信息 提交或回滚事务
这篇博客本来打算写JDK和cglib动态代理的源码介绍的,写着写着就写成介绍代理都有哪些类型及实现方式了,再写篇幅就有点长了,所以放到下篇博客说明。
标签:style blog io 使用 java ar for 数据 2014
原文地址:http://blog.csdn.net/lidatgb/article/details/38775631