这里,介绍两种非注解的动态代理:一种是JDK动态代理,使用的是java.lang.reflect
包中的InvocationHandler、Method和Proxy;另一种是CGlib动态代理:需要Spring
包中的,cglib-nodep.jar文件。
一.JDK动态代理
注意:JDK动态代理的对象,必须实现接口。
package com.zyy.service; /** * Created by CaMnter on 2014/8/20. */ public interface PersonService_3 { public void save(String name); public void update(Integer personId, String name); public void delete(Integer personId); }
package com.zyy.service.impl; import com.zyy.service.PersonService_3; /** * Created by CaMnter on 2014/8/21. */ /** * JDKProxyFactory 代理的对象 要求实现接口 */ /* * 1.拦截所有的业务方法 * 2.判断用户是否有权限 * 3.有权限则允许他执行业务方法,没权限则不允许(这里根据user是否为null作为判断) */ public class PersonServiceBean_3 implements PersonService_3 { private String user = null; public String getUser() { return user; } public PersonServiceBean_3() { } public PersonServiceBean_3(String user) { this.user = user; } public void save(String name) { System.out.println("***** save " + name + " *****"); } public void update(Integer personId, String name) { System.out.println("***** update *****"); } public void delete(Integer personId) { System.out.println("***** delete *****"); } }
package com.zyy.aop; import com.zyy.service.impl.PersonServiceBean_3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Created by CaMnter on 2014/8/21. */ /** * JDK的动态代理 * <p/> * 但是要求目标对象实现接口,因为 * Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), * this.targetObject.getClass().getInterfaces(), this); */ /* * * 当用户调用代理对象 * 代理对象调用invoke * 判断权限(if) * 然后invoke方法中再委派给目标对象 * (Object result = method.invoke(this.targetObject,args) ;) * */ public class JDKProxyFactory implements InvocationHandler { //代理的目标对象 private Object targetObject; public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; /* * 第一个参数设置代码使用的类装载器,一般采用跟目标类相同的类装载器 * 第二个参数设置代理类实现的接口 * 第三个参数设置回调对象,当代理对象的方法被调用时,会委派给该参数指定对象的invoke方法 */ return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), this.targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PersonServiceBean_3 bean = (PersonServiceBean_3) this.targetObject; Object result = null; //权限过滤 代理对象有 user的值 才能调用它的方法 if (bean.getUser() != null) { result = method.invoke(this.targetObject, args); } return result; } }
junit4.4.测试代码:
@Test public void jdkproxyTest() { //JDK动态代理 JDKProxyFactory jdkProxyFactory = new JDKProxyFactory(); System.out.println("***** JDK动态代理 *****"); System.out.println("***** 没有user值实例化目标 *****"); PersonService_3 personService_3 = (PersonService_3) jdkProxyFactory.createProxyInstance(new PersonServiceBean_3()); System.out.println("----- 无法调用方法 -----"); personService_3.save("07"); System.out.println("***** 有user值实例化目标 *****"); personService_3 = (PersonService_3) jdkProxyFactory.createProxyInstance(new PersonServiceBean_3("CaMnter")); System.out.println("----- 可以调用方法 -----"); personService_3.save("07"); }
没有user值实例化目标,就在JDK代理那里过滤掉了,就无法使用方法。
二.CGlib动态代理
目标不需要接口,但是实现CBlib代理需要Spring 的依赖包cglib-nodep.jar。
package com.zyy.service.impl; /** * Created by CaMnter on 2014/8/21. */ /** * CGlibProxyFactory 代理的对象 不要求实现接口 */ /* * * 1.拦截所有的业务方法 * 2.判断用户是否有权限 * 3.有权限则允许他执行业务方法,没权限则不允许(这里根据user是否为null作为判断) */ public class PersonServiceBean_4 { private String user = null; public String getUser() { return user; } public PersonServiceBean_4() { } public PersonServiceBean_4(String user) { this.user = user; } public void save(String name) { System.out.println("***** save " + name + " *****"); } public void update(Integer personId, String name) { System.out.println("***** update *****"); } public void delete(Integer personId) { System.out.println("***** delete *****"); } }
package com.zyy.aop; /** * Created by CaMnter on 2014/8/21. */ import com.zyy.service.impl.PersonServiceBean_4; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * CGllib的动态代理 */ /* * * 当用户调用代理对象 * 代理对象调用invoke * 判断权限(if) * 然后invoke方法中再委派给目标对象 * (Object result = method.invoke(this.targetObject,args) ;) * */ public class CGlibProxyFactory implements MethodInterceptor { private Object targetObject; public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; //CGlib代理 Enhancer enhancer = new Enhancer(); //CGlib代理 就是继承了目标类 ,对目标类中所用非final 的进行覆盖 enhancer.setSuperclass(this.targetObject.getClass()); //当被目标类调用的时候 enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { PersonServiceBean_4 bean = (PersonServiceBean_4) this.targetObject; Object result = null; //权限过滤 代理对象有 user的值 才能调用它的方法 if (bean.getUser() != null) { result = method.invoke(this.targetObject, objects); } return result; } }
junit4.4测试代码:
@Test public void cglibproxyTest() { //CGlib动态代理 CGlibProxyFactory cGlibProxyFactory = new CGlibProxyFactory(); System.out.println("***** CGlib动态代理 *****"); System.out.println("***** 没有user值实例化目标 *****"); PersonServiceBean_4 personServiceBean_4 = (PersonServiceBean_4) cGlibProxyFactory.createProxyInstance(new PersonServiceBean_4()); System.out.println("----- 无法调用方法 -----"); personServiceBean_4.save("07"); System.out.println("***** 有user值实例化目标 *****"); personServiceBean_4 = (PersonServiceBean_4) cGlibProxyFactory.createProxyInstance(new PersonServiceBean_4("CaMnter")); System.out.println("----- 可以调用方法 -----"); personServiceBean_4.save("07"); }
没有user值实例化目标,就在CGlib代理那里过滤掉了,就无法使用方法。