本文共 4462 字,大约阅读时间需要 14 分钟。
Proxy Pattern: Provide a surrogate or placeholder for another object to control access to it.
代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。代理模式结构图
1.静态代理
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类.package Static;public interface UserDao { void save();}
package Static;public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("----已经保存数据!----"); }}
package Static;public class UserDaoProxy implements UserDao{ //接收保存目标对象 private UserDao target; public UserDaoProxy(UserDao target){ this.target=target; } public void save() { System.out.println("开始事务..."); target.save();//执行目标对象的方法 System.out.println("提交事务..."); }}
package Static;public class TestMain { public static void main(String[] args) { //目标对象 UserDao userDao=new UserDaoImpl(); UserDaoProxy userDaoProx=new UserDaoProxy(userDao); userDaoProx.save(); }}
缺点:
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.
2.动态代理
1
package Static;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 创建动态代理对象 * 动态代理不需要实现接口,但是需要指定接口类型 */public class ProxyFactory { //维护一个目标对象 private Object target; public ProxyFactory(Object target){ this.target=target; } //给目标对象生成代理对象 public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始事务2"); //执行目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务2"); return returnValue; } } ); }}
package Static;public class App { public static void main(String[] args) { // 目标对象 UserDao target=new UserDaoImpl(); // 【原始的类型 class Static.UserDaoImpl】 System.out.println(target.getClass()); // 给目标对象,创建代理对象 UserDao proxy = (UserDao) new ProxyFactory(target).getProxyInstance(); // class com.sun.proxy.$Proxy0 内存中动态生成的代理对象 System.out.println(proxy.getClass()); // 执行方法 【代理对象】 proxy.save(); }}
2.Cglib代理
上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理 如果目标对象没有实现接口,用Cglib代理package Cglib;public class UserDao { public void save() { System.out.println("----已经保存数据!----"); }}
package Cglib;import org.springframework.cglib.proxy.Enhancer;import org.springframework.cglib.proxy.MethodInterceptor;import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * Cglib子类代理工厂 * 对UserDao在内存中动态构建一个子类对象 *///1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,// 所以直接引入spring-core-3.2.5.jar即可.public class ProxyFactory implements MethodInterceptor { //维护目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } //给目标对象创建一个代理对象 public Object getProxyInstance(){ //1.工具类 Enhancer en = new Enhancer(); //2.设置父类 en.setSuperclass(target.getClass()); //3.设置回调函数 en.setCallback(this); //4.创建子类(代理对象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开始事务..."); //执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务..."); return returnValue; }}
package Cglib;import Static.ProxyFactory;import Static.UserDao;import Static.UserDaoImpl;public class App { public static void main(String[] args) { // 目标对象 Static.UserDao target=new UserDaoImpl(); // 【原始的类型 class Static.UserDaoImpl】 System.out.println(target.getClass()); //代理对象 UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance(); // class com.sun.proxy.$Proxy0 内存中动态生成的代理对象 System.out.println(proxy.getClass()); // 执行方法 【代理对象】 proxy.save(); }}
转载地址:http://pwrd.baihongyu.com/