java jdk与cglib动态代理模式的认识和实现

被刻印的时光 ゝ 提交于 2019-11-30 15:59:31

1.使用java jdk Proxy实现动态代理,该原理是反射机制。

建立一个普通的接口

package com.tester.cls.design.mode;

public interface IUser {

	public String getName();

	public void setName(String name);
	
	public void setUser(int id,String name);
	
	public int getId();

	public void setId(int id);
}

构建一个实现类(简单的javaBean)

package com.tester.cls.design.mode;


public class User  implements IUser{

	private int id;
	
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public void setUser(int id,String name) 
	{
		setId(id);
		setName(name);
	}
	
	@Override
	public String toString() {
		return super.toString();
	}
	
}

实现代理

InvocationHandler实质是拦截器,用来拦截动态代理的方法调用。

Proxy才是动态代理,拦截器拦截Proxy生成的代理对象的方法

package com.tester.cls.design.mode;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public  class ObjectProxy implements InvocationHandler{

	IUser delegateTarget = null;

		public  IUser delegate(IUser delegateTarget)
	{
		this.delegateTarget =  delegateTarget;
		return  (IUser) Proxy.newProxyInstance(ObjectProxy.class.getClassLoader(), delegateTarget.getClass().getInterfaces(),this);
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println(method.getName()+"-"+method.getReturnType());
		return method.invoke(delegateTarget, args);
	}
	

}

测试,测试一下

public static void main(String[] args) {
		
		User u = new User();
		
		ObjectProxy objHandler = new ObjectProxy();
		IUser delegate = objHandler.delegate(u); //注意,返回值的类型是注解类型
		
		delegate.setUser(2014, "zhangsan");
		
		System.out.println(delegate.getId()+"-"+delegate.getName());
		System.out.println(u.getId()+"-"+u.getName());
		
		u.setUser(2048, "张三");
		
		System.out.println(delegate.getId()+"-"+delegate.getName());
		System.out.println(u.getId()+"-"+u.getName());
	
	}

输出结果

2014-zhangsan
2014-zhangsan
2048-张三
2048-张三


2.使用cglib.jar实现动态代理,原理是操作底层字节码

Cglib实现动态代理,Cglib的效率高于JDK动态代理,因为Cglib是有底层字节码方式生产一个代理类的(此观点来自于互联网,本人水平有限,目前只将概念)。

cglib使用底层ASM实现动态类的继承(很牛逼吧,我们日常使用的类是静态继承的,这简直是逆天的赶脚啊~~),能力好的童鞋建议去看源码。

(注:此处不提供 cglib.jar下载)

public class CglibProxy implements MethodInterceptor{
 private Enhancer enhancer = new Enhancer();
 public Object getProxy(Class clazz){
  //设置需要创建子类的类
  enhancer.setSuperclass(clazz); 
  enhancer.setCallback(this);
  //通过字节码技术动态创建子类实例
  return enhancer.create(); 
 }
 //实现MethodInterceptor接口方法
 public Object intercept(Object obj, Method method, Object[] args,
   MethodProxy proxy) throws Throwable {
  System.out.println("前置代理");
  //通过代理类调用父类中的方法
  Object result = proxy.invokeSuper(obj, args);
  System.out.println("后置代理");
  return result;
 }
}

测试如下,但不提供结果

public class DoCGLib {
 public static void main(String[] args) {
  CglibProxy proxy = new CglibProxy();
  //通过生成子类的方式创建代理类
  SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
  proxyImp.say();
 }
}


好了,这就是动态代理的基本认识

try doing it;

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!