来自视频教程的笔记http://wenku.baidu.com/course/view/192a0066f5335a8102d22000?cid=5
代理模式顾名思义,有一个代理类,一个被代理的目标对象,代理类可以在目标类的方法前后做一些事情。
实际上,一旦配置完毕,目标类的所有方法前后都会做那些事情。
我用自己的话总结一下,别喷。
有两种方法 一种是java反射机制,另一种效率比较好,采用cglib,后者也是spring AOP采用的技术。
直接上例子
一个接口,不一定是dao举例子而已
public interface StudentDao { public void saveStudent(); public void queryStudent(); }
一个实现以上接口的类。
public class StudentDaoImpl implements StudentDao { @Override public void saveStudent() { System.out.println("保存学生资料。。。。"); } @Override public void queryStudent() { System.out.println("查询学生资料。。。。"); } }
代理 类
public class DAOProxy implements InvocationHandler { private Object originalObject; public Object bind(Object obj) { this.originalObject = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } void preMethod() { System.out.println("----执行方法之前----"); } void afterMethod() { System.out.println("----执行方法之后----"); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; preMethod(); result = method.invoke(this.originalObject, args); afterMethod(); return result; } }
##
代理类继承了java.lang.reflect.InvocationHandler;
bind这个方法绑定代理对象和目标对象,其中:Proxy.newProxyInstance接收三个参数,①类加载器②目标对象实现的所有接口③代理对象本身
bind方法把目标对象拿到,绑定好,又作为返回值传递回来,所以绑定之后的目标对象是增加了代理功能后的了
第二个参数是接口,所以,用java反射机制实现动态代理,那目标对象一定要实现接口
invoke方法也接收三个参数:①代理对象②要用代理的方法③这个方法的参数
我之前只学过基础java反射,知道这是反射的方法,只是多了一个代理对象
测试类如下
public class TestDaoProxy extends TestCase { public void testDaoProxy(){ StudentDao studentDao = new StudentDaoImpl(); DAOProxy daoProxy=new DAOProxy(); studentDao = (StudentDao)daoProxy.bind(studentDao); studentDao.queryStudent(); } }
换成目标类中的另一个方法也是通用的。
下面是第二中方法,第二中方法使用cglib技术,需要jar包,jar包在spring的依赖包中有,3.0已经继承进主jar包,2.5有单独的jar包
cglib和前一个方法的不同是没有接口也可以
目标类如下
public class StudentDao { public void saveStudent() { System.out.println("保存学生资料。。。。"); } public void queryStudent() { System.out.println("查询学生资料。。。。"); } }
代理类如下
public class DAOCglibProxy implements MethodInterceptor { private Object originalObject; public Object bind(Object obj) { this.originalObject = obj; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(obj.getClass()); enhancer.setCallback(this); return enhancer.create(); } void preMethod() { System.out.println("----执行方法之前----"); } void afterMethod() { System.out.println("----执行方法之后----"); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { preMethod(); Object result = proxy.invokeSuper(obj, args); afterMethod(); return result; } }
测试方法如下
public void testDAOCglibProxy() { StudentDao studentsDao = new StudentDao(); DAOCglibProxy proxy = new DAOCglibProxy(); studentsDao = (StudentDao) proxy.bind(studentsDao); studentsDao.queryStudent(); }
cglib实际上是通过继承出一个子类实现的代理。可以把Enhancer看做那个子类的生成器 ,所以在bind方法中,指定父类,然后绑定好代理对象就可以了
指定父类:enhancer.setSuperclass(obj.getClass());
绑定代理方法:enhancer.setCallback(this);
然后返回创建好的已经加了代理的目标对象:return enhancer.create();
在测试类中使用的时候很简单,只要绑定好,然后执行就行。
可见还是cglib这个方法更方便,而且据说效率最高。所以spring采用之。