JDK代理和CGlib代理

     代理模式,是很多框架中应用到的基础,例如mybatis中对于配置环境的元素的读取,以及推荐使用的mapper的接口,其中使用到的就是JDK动态代理技术,然而在spring中也有对应的体现,然而会产生疑问,仅提供一个接口,怎么会执行呢?其实代理的本质就是继承。

好了,我们慢慢的一点点解答:

JDK静态代理:

    我们设计了一个HelloService接口和其对应的实现类HelloServiceImpl类:

public interface HelloService {

	public void sayHello(String name);
}
对应的实现类:

public class HelloServiceImpl implements HelloService {

	@Override
	public void sayHello(String name) {
		// TODO Auto-generated method stub
		System.out.println("hello " + name);
	}

}
如果我们先通过代理的方法来实现的话,我们首先要做的是构建一个代理类,代理类也需要实现HelloService接口:

public class JDKSTA implements HelloService {
	private HelloServiceImpl helloServiceImpl;
	
	public JDKSTA(HelloServiceImpl helloServiceImpl){
		this.helloServiceImpl = helloServiceImpl;
	}

	@Override
	public void sayHello(String name) {
		System.out.println("我准备说hello了");
		helloServiceImpl.sayHello(name);
		System.out.println("我说过hello了");
	}
}
对应的测试类:

public class JDKstatEST {

	public static void main(String[] args) {
		//创建JDK代理对象
		HelloService proxy= new JDKSTA(new HelloServiceImpl());
		proxy.sayHello("zhang san");
	}
}
这样则完成了JDK的静态代理的过程。


JDK动态代理:

HelloService接口和其对应的实现类都不变,我们重新设计一个新的代理类,这次的代理类需要继承InvocationHandler接口,其他的说明在注释中体现了:

扫描二维码关注公众号,回复: 1106330 查看本文章
public class HelloServiceProxy  implements InvocationHandler{

	private Object target;
	
	/**
	 * 帮绑定委托对象并方辉一个代理类
	 * @param target
	 * @return
	 */
	public Object bind(Object target){
		this.target = target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
			 this);
	}
	
	
	@Override
	/**
	 * 通过代理对象调用方法首先进入这个方法
	 * @param proxy   代理对象
	 * @param method 被调用的方法
	 * @param 方法的参数
	 */
	public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
		System.out.println("############JDK动态代理#########");
		Object result = null;
		System.out.println("我准备说hello");
//		//执行方法,相当于调用helloServiceImpl类的sayHello方法
//		//此invoke方法为Method类里面的incoke方法,而不是reflect里面的invoke方法
//      //此方法实现真正的由接口调用实现类的方法
		result =method.invoke(target, args);
//		//反射方法后调用
		System.out.println("我说过hello了");
		return result;
	}
}
对应的测试类为:

public class HelloServiceMain {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//生成一个代理类对象
		HelloServiceProxy HelloHandler = new HelloServiceProxy();
		//代理接口
		HelloService proxy = (HelloService)HelloHandler.bind(new HelloServiceImpl());
		proxy.sayHello("zhang san");
	}
}

CGlib动态代理:

JDK代理需要我们提供接口,必须有接口才能够实现动态,静态代理的过程,而CGlib可以不用提供接口,仅提供实现类就可以完成动态代理的工作,当然也可以完成有接口的动态代理,当然这个就体现不了CGlib的优势。重新设计一个符合CGlib使用的动态代理类:
public class HelloServiceCGlib implements MethodInterceptor{

	private Object target;
	
	public Object getInstance (Object target){
		this.target = target;
		//下面类似于JDK动态代理的绑定过程
		Enhancer enhancer = new Enhancer();
		//指定父类,不必指定接口
		enhancer.setSuperclass(this.target.getClass());
		//回调方法
		enhancer.setCallback(this);
		//创建代理对象
		return enhancer.create();
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("###########我是CGLIB###########");
		//反射方法的调用
		System.out.println("我准备说hello");
		Object returnObj = proxy.invokeSuper(obj, args);
		System.out.println("我说过hello了");
		return returnObj;
	}
	
}
对应的测试类:
public class HelloServiceMain {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//生成一个代理类对象
		//cglib需要指定父类和回调方法。当然cglib也可以与Java动态代理一样面向接口,因为本质是继承。
		HelloServiceCGlib HelloHandler = new HelloServiceCGlib();
		//代理接口
		HelloService proxy = (HelloService)HelloHandler.getInstance(new HelloServiceImpl());
		proxy.sayHello("zhang san");
	}
}

测试结果为:










猜你喜欢

转载自blog.csdn.net/qq_18870127/article/details/79798030