天天看点

代理实现机制,Java中动态代理和cglib动态代理的实现机制

代理是Java中一种常见的设计模式,代理不能够直接访问的类,通过代理类实现对内部

不能够直接访问的类的方法的调用,其特征是代理类与需要代理的类(委托类)具有相同

的功能,甚至是同一个接口的实现类。按照代理类存在的时期分为静态代理和动态代理两类。

静态代理:由程序创建生成源码,再对其进行编译,在程序运行前class文件已经存在。

动态代理:在程序运行的时候通过反射机制创建。

静态代理例子:

package core.java.proxy.stac;

public interface ProductService {
	
	public void detail(String productNo);

}

package core.java.proxy.stac;

public class ProductServiceImpl implements ProductService{

	@Override
	public void detail(String productNo) {
		System.out.println("这是编号为" + productNo + "的详细数据");
		
	}

}

package core.java.proxy.stac;

public class ProductProxy implements ProductService{
	
	private ProductServiceImpl productService;
	
	public ProductProxy(ProductServiceImpl productServiceImpl){
		this.productService = productServiceImpl;
	}

	@Override
	public void detail(String productNo) {
		System.out.println("product proxy before.............");
		productService.detail(productNo);
		System.out.println("product proxy after.............");
	}

}

package core.java.proxy.stac;

public class StacProxyTest {
	
	public static void main(String[] args) {
		ProductProxy proxy = new ProductProxy(new ProductServiceImpl());
		proxy.detail("30001245");
	}
}
           

输出结果:

product proxy before.............

这是编号为30001245的详细数据

product proxy after.............

由上面的例子可以看出静态代理类其实是对实现类的引用然后再对其方法进行调用,

并且静态代理类只能为一个类服务,如果有很多类需要代理就会创建很多代理类,

代码中出现大量的代理类。

为了解决静态代理带来的不便,Java中提供了动态代理的实现机制,如果想创建代理类

只需要实现InvocationHandler接口,实现其invoke方法即可。

Java动态代理实现例子:

package core.java.proxy;


/**
 * 实现的业务接口
 * @author admin
 *
 */
public interface UserService {
	
	public void sayHello(String name);

}

package core.java.proxy;


/**
 * 实际业务的实现类
 * @author admin
 *
 */
public class UserServiceImpl implements UserService{

	@Override
	public void sayHello(String name) {
		System.out.println("hello " + name + "!");
	}

}

package core.java.proxy;

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


/**
 * 业务代理类
 * @author admin
 *
 */
public class UserProxy implements InvocationHandler{
	
	/**
	 * 需要代理的原生对象
	 */
	private Object obj;
	
	public UserProxy(Object obj) {
		super();
		this.obj = obj;
	}

	/**
	 * @param proxy 被代理的对象
	 * @param method 需要调用的方法
	 * @param args  方法调用时需要的参数
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("proxy before..........");
		Object result = method.invoke(obj, args);
		System.out.println("proxy after............");
		return result;
	}
}

package core.java.proxy;

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


public class ProxyTest {
	
	public static void main(String[] args) {
		UserService userService = new UserServiceImpl();
		InvocationHandler invocationHandler = new UserProxy(userService);
		UserService proxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler);
		proxy.sayHello("zhangsan");
	}

}
           

输出结果:

proxy before..........

hello zhangsan!

proxy after............

动态代理可以实现所有需要代理的原生类的功能,解决了静态代理的缺陷。但是动态代理

也有自身的缺陷,就是动态代理只能代理有实现类的接口,这就需要代理的接口类必须有

实现类,这样程序中也会出现大量的实现类,为了解决这一缺陷,cglib就是对这一缺陷

的弥补。cglib的原理就是对目标类生成一个子类,覆盖其方法进行增强。因为采用的是

Java中继承的机制,因此不能对用了final修饰符的类进行代理。

cglib动态代理例子:

package core.java.proxy.cglib;

public interface TicketService {
	
	public void sell();

}

package core.java.proxy.cglib;

public class TicketBiz {
	
	public void sell(){
		System.out.println("卖出一张票");
	}

}

package core.java.proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProxyCglib implements MethodInterceptor{
	
	private Object target;
	
	public Object createProxy(Object target){
		this.target = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.target.getClass());
		enhancer.setCallback(this);
		enhancer.setClassLoader(this.getClass().getClassLoader());
		return enhancer.create();
	}

	@Override
	public Object intercept(Object arg, Method method, Object[] objects,
			MethodProxy proxy) throws Throwable {
		System.out.println("sell ticket before..........");
		proxy.invokeSuper(arg, objects);
		System.out.println("sell ticket after..........");
		return null;
	}

}

package core.java.proxy.cglib;


public class CglibProxyTest {
	
	public static void main(String[] args) {
		ProxyCglib proxyCglib = new ProxyCglib();
		TicketBiz ticketBiz = (TicketBiz)proxyCglib.createProxy(new TicketBiz());
		ticketBiz.sell();
	}

}
           

输出结果:

sell ticket before..........

卖出一张票

sell ticket after..........

静态代理和动态代理比较:

静态代理预先生成好代理类通过编译生成class文件,程序运行时就能调用,

动态代理是程序运行时根据反射机制生成代理类,因此静态代理的速度要

比动态代理快一些。