[ JDK生成代理 ]
JDK中给我们提供了一个Proxy类可以动态的给我们生成代理.
假定我们要做一个权限管理系统, 需要控制用户对某一个方法的访问. 如果user为null, 那么不让用户访问save方法.
① 接口类: PersonService
- public interface PersonService {
- public void save();
- }
② 实现类: PersonServiceImpl
- public class PersonServiceImpl implements PersonService {
- private String user;
-
- public PersonServiceImpl(){
- }
-
- public PersonServiceImpl(String user) {
- this.user = user;
- }
-
- public void save() {
- System.out.println("执行了save()方法");
- }
-
- public String getUser() {
- return user;
- }
- }
③ 生成代理类工厂: JDKProxyFactory
- public class JDKProxyFactory implements InvocationHandler {
- private Object targetObject;
-
- public Object createProxyIntance(Object targetObject) {
- this.targetObject = targetObject;
-
-
-
-
-
- return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),
- this.targetObject.getClass().getInterfaces(),
- this);
- }
-
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- PersonServiceImpl ps = (PersonServiceImpl) this.targetObject;
- Object result = null;
- if (ps.getUser() != null) {
- result = method.invoke(targetObject, args);
- }
- return result;
- }
- }
④ 测试一把:
- public class PersonServiceImplTest {
- @Test
- public void testJDKProxy() {
- JDKProxyFactory factory = new JDKProxyFactory();
- PersonService personService = (PersonService) factory.createProxyIntance(new PersonServiceImpl("zhangsan"));
- personService.save();
- }
- }
[ CGLIB生成代理 ]
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类。
使用CGLIB生成代理需要引入cglib-nodep-2.1_3.jar
① CBLIG生成代理工厂: CGlibProxyFactory
- public class CGlibProxyFactory implements MethodInterceptor {
- private Object targetObject;
-
- public Object createProxyIntance(Object targetObject) {
- this.targetObject = targetObject;
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(this.targetObject.getClass());
- enhancer.setCallback(this);
- return enhancer.create();
- }
-
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;
- Object result = null;
- if (bean.getUser() != null) {
- result = methodProxy.invoke(targetObject, args);
- }
- return result;
- }
- }
② 测试一把
- public class PersonServiceImplTest {
- @Test
- public void testCGLIBProxy() {
- CGlibProxyFactory factory = new CGlibProxyFactory();
- PersonService personService = (PersonServiceImpl) factory.createProxyIntance(new PersonServiceImpl("lisi"));
- personService.save();
- }
- }
[ 比较两种代理 ]
1. 使用JDK的动态代理, 被代理类一定要实现了某个接口, 而使用CGLIB, 被代理类没有实现任何接口也可以实现动态代理功能,
2. 因为采用的是继承, 所以cglib无法对使用final修饰的类使用代理.
3. CGLIB的速度要远远快于JDK Proxy动态代理.