博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java代理模式
阅读量:5337 次
发布时间:2019-06-15

本文共 5864 字,大约阅读时间需要 19 分钟。

一.静态代理

   代理类在代码运行前存在,这种代理的方式称为静态代理,这种方式的代理类是通我们自己编写来实现,一般情况下,静态代理模式的代理类和委托类实现同一个接口。

简单地代码实现如下:Lets GO

  

/** * @Author zhangfu * @Date 23:17 2019/8/5  * 接口 */public interface UserManager {   public void addUser(String userId, String userName);   public  void delUser(String userId);   public  String findUser(String userId);   public void modifyUser(String userId, String userName);}

  

/** * @Author: 13394 * @CreateDate: 2019/8/5 23:22 * 真实对象 */public class UserManagerImpl implements UserManager {    @Override    public void addUser(String userId, String userName) {        System.out.println("添加用户!!!!!!!");    }    @Override    public void delUser(String userId) {        System.out.println("删除用户!!!!!!!");    }    @Override    public String findUser(String userId) {        System.out.println("查询用户!!!!!!!");        return null;    }    @Override    public void modifyUser(String userId, String userName) {        System.out.println("修改用户!!!!!!!");    }}

 

/** * @Author: 13394 * @CreateDate: 2019/8/5 23:25  * 代理类 */public class ProxyUserManagerImpl implements UserManager {    private UserManager userManager;    public ProxyUserManagerImpl(UserManager userManager) {        this.userManager = userManager;    }    @Override    public void addUser(String userId, String userName) {        System.out.println("添加用户开始!!!!!!!!!!!!!!!");        userManager.addUser(userId,userName);        System.out.println("添加用户结束!!!!!!!!!!!!!!!!!");    }    @Override    public void delUser(String userId) {    }    @Override    public String findUser(String userId) {        return null;    }    @Override    public void modifyUser(String userId, String userName) {    }}

 

/** * @Author: 13394  * 测试类 */public class ClientTest {          public static void main(String[] args) {        UserManager userManager=new ProxyUserManagerImpl(new UserManagerImpl());        userManager.addUser("1","张三");    }}

二.动态代理,JDK内置的Proxy实现  

  什么是动态代理:

代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。

在使用动态代理时,我们需要定义一个位于代理类与委托类之间的中介类,这个中介类被要求实现InvocationHandler接口

public interface Subject {		void hello(String str);	String bye();}
//委托类 public class RealSubject  implements Subject{	@Override    public void hello(String str) {        System.out.println("Hello  " + str);    }    @Override    public String bye() {        System.out.println("Goodbye");        return "Over";    }    }
//中介类 public class InvocationHandlerDemo implements InvocationHandler {	// 这个就是我们要代理的真实对象	private Object subject;	// 构造方法,给我们要代理的真实对象赋初值	public InvocationHandlerDemo(Object subject) {		this.subject = subject;	}		/*     * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数     * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象     * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了     * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上     */	public Object createProxyIntance(){		return Proxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), this);	}	@Override	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {		// 在代理真实对象前我们可以添加一些自己的操作		System.out.println("Before method");		System.out.println("Call Method: " + method);		// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用		Object obj = method.invoke(subject, args);		// 在代理真实对象后我们也可以添加一些自己的操作		System.out.println("After method");		return obj;	}}
public class ClientTest {   public static void main(String[] args) {	   // 我们要代理的真实对象       Subject realSubject = new RealSubject();       //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的       InvocationHandlerDemo handler = new InvocationHandlerDemo(realSubject);        Subject subject=(Subject)handler.createProxyIntance();       String result = subject.bye();       System.out.println("Result is: " + result);       System.out.println("代理的类型:"+subject.getClass().getName());   }}

 中介类持有一个委托类对象引用,在invoke方法中调用了委托类对象的相应方法,通过聚合方式持有委托类对象引用,把外部对invoke的调用最终都转为对委托类对象的调用。这不就是我们上面介绍的静态代理的一种实现方式吗?实际上,中介类与委托类构成了静态代理关系,在这个关系中,中介类是代理类,委托类就是委托类; 代理类与中介类也构成一个静态代理关系,在这个关系中,中介类是委托类,代理类是代理类。也就是说,动态代理关系由两组静态代理关系组成,这就是动态代理的原理

三.动态代理,cjlib 代理

    cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。而java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

<dependency>

<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.1</version>
</dependency>

委托类是java动态代理的代码。上面

/** * cjlib 动态代理 * @author 86133 * */public class CjlibDynamicProxy implements MethodInterceptor {		Object targetObject;  //目标对象	/**	 * 动态生成一个新的类,使用父类的无参构造方法创建一个指定了特定回调的代理实例	 * @param obj	 * @return	 */	public Object getProxyObject(Object obj){		this.targetObject=obj;		 //增强器,动态代码生成器		Enhancer enhancer=new Enhancer();		 //回调方法		enhancer.setCallback(this);		//设置生成类的父类类型		enhancer.setSuperclass(targetObject.getClass());		//动态生成字节码并返回代理对象		return enhancer.create();	}	@Override	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {		Object result = proxy.invoke(targetObject,args);		return result;	}}

  

public class ClientTest {   public static void main(String[] args) {	       CjlibDynamicProxy cjlibDynamicProxy=new CjlibDynamicProxy();       Subject subjects=(Subject) cjlibDynamicProxy.getProxyObject(realSubject);       String result1 = subjects.bye();       System.out.println("结果:"+result+"代理类型:"+subjects.getClass().getName());}}

 四. SpringAop 的两种代理方式(Jdk的动态代理和Cjlib的动态代理)        

      JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。 CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final 

       

   如果spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。

 如果spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通知,并且把对这个子类的调用委托到目标类。

 

参考博客:,

                  ,

                   (动态代理源码解析) 

  

  

 

  

 

转载于:https://www.cnblogs.com/xiaofuzi123456/p/11311929.html

你可能感兴趣的文章
详谈js面向对象 javascript oop,持续更新
查看>>
关于这次软件以及pda终端的培训
查看>>
jQuery上传插件Uploadify 3.2在.NET下的详细例子
查看>>
如何辨别一个程序员的水平高低?是靠发量吗?
查看>>
新手村之循环!循环!循环!
查看>>
正则表达式的用法
查看>>
线程安全问题
查看>>
SSM集成activiti6.0错误集锦(一)
查看>>
下拉刷新
查看>>
linux的子进程调用exec( )系列函数
查看>>
MSChart的研究
查看>>
C# 索引器
查看>>
MySQLdb & pymsql
查看>>
zju 2744 回文字符 hdu 1544
查看>>
delphi 内嵌汇编例子
查看>>
【luogu P2298 Mzc和男家丁的游戏】 题解
查看>>
前端笔记-bom
查看>>
MATLAB作图方法与技巧(一)
查看>>
上海淮海中路上苹果旗舰店门口欲砸一台IMAC电脑维权
查看>>
Google透露Android Market恶意程序扫描服务
查看>>