动态代理(dynamic proxy),初学版

参考博客:

http://blog.csdn.net/heyutao007/article/details/49738887

https://www.jianshu.com/p/58759fef38b8

其中简书博客中,代码有些细节上的错误,本篇基本参照的是第一个链接

一、准备

本人1.8的jdk,cglib需要依赖的架包(下面的链接是我使用的架包)

cglib:http://mvnrepository.com/artifact/cglib/cglib/3.2.6

asm:http://mvnrepository.com/artifact/org.ow2.asm/asm/6.0

特别注意:cglib和asm架包的版本要配套,如果两个jar之间版本差别大,可能会导致各种Exception。

二、正题

公用类:

public interface UserService {
	String getName(int id);
	Integer getAge(int id);
}
public class UserServiceImpl implements UserService {

	@Override
	public String getName(int id) {
		System.out.println("------getName------");
		return "Tom";
	}

	@Override
	public Integer getAge(int id) {
		System.out.println("------getAge------");
		return 10;
	}

}
1、JDK自带动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

	private Object target;
	
	MyInvocationHandler() {
		super();  
	}
	
	MyInvocationHandler(Object target) {
		super();  
		this.target = target;  
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if ("getName".equals(method.getName())) {
			System.out.println("++++++before " + method.getName() + "++++++");
			Object result = method.invoke(target, args);
			System.out.println("++++++after " + method.getName() + "++++++");
			return result;
		} else {
			Object result = method.invoke(target, args);
			return result;
		}
	}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test1 {
	public static void main(String[] args) {
		UserService userService = new UserServiceImpl();
		InvocationHandler invocationHandler = new MyInvocationHandler(userService);
		UserService userServiceProxy = (UserService)Proxy.newProxyInstance(
				userService.getClass().getClassLoader(),  
				userService.getClass().getInterfaces(),
				invocationHandler);
		System.out.println(userServiceProxy.getName(1));
		System.out.println(userServiceProxy.getAge(1));
	}
}
2、CGLIB自动代理
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

	@Override
	public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
		System.out.println(method.getName());
		Object o1 = methodProxy.invokeSuper(o, args);
		System.out.println("++++++before " + methodProxy.getSuperName() + "++++++");
		return o1;
	}
}
import net.sf.cglib.proxy.Enhancer;

public class Test2 {

	public static void main(String[] args) {
		CglibProxy cglibProxy = new CglibProxy();

		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(UserServiceImpl.class);
		enhancer.setCallback(cglibProxy);

		UserService o = (UserService)enhancer.create();
		System.out.println(o.getName(1));
		System.out.println(o.getAge(1));
	}
}

三、总结

别人的总结:

dk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。
总的来说,反射机制在生成类的过程中比较高效,
而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。
还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。

自己的总结:动态代理的优点如下:在不修改原接口的情况下,对该接口进行扩展。

留下的疑惑:1、还没有完全理解动态代理的原理。

                    2、动态代理在什么情况下应用最好?




猜你喜欢

转载自blog.csdn.net/h996666/article/details/79415483