JDK的动态代理,经常被用来动态地创建对象的代理。JDK的动态代理用起来非常简单,但是有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理没有实现接口,还可以使用cglib包来完成代理。
cglib的底层通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的代理类。所以基于cglib开发时需要引入cglib的jar包和ASM的jar包。
下面的例子是基于cglib-2.2.2.jar和asm-all-3.0.jar。
先是一个普通的java类:
package cglib; public class BookServiceBean { public void create() { System.out.println("create() is running !"); } public void query() { System.out.println("query() is running !"); } public void update() { System.out.println("update() is running !"); } public void delete() { System.out.println("delete() is running !"); } }
下面的类将基于cglib为上面的类生成一个代理:
这个类是重点,getDaoBean将返回一个代理, enhancer.setSuperclass(cls);指明了为cls生成代理, enhancer.setCallback(this);指明MyCglibProxy为拦截器,
intercept方法将拦截cls中的方法并作处理。
package 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 MyCglibProxy implements MethodInterceptor { public Enhancer enhancer = new Enhancer(); private String name; public MyCglibProxy(String name) { this.name = name; } public Object getDaoBean(Class cls) { enhancer.setSuperclass(cls); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object object, Method method, Object [ ] args, MethodProxy methodProxy) throws Throwable { System.out.println("MyCglibProxy is running!"); Object result = methodProxy.invokeSuper(object, args); return result; } }
写一个简单的工厂:
package cglib; public class BookServiceFactory { private BookServiceFactory() { } public static BookServiceBean getProxyInstance(MyCglibProxy myProxy){ return (BookServiceBean)myProxy.getDaoBean(BookServiceBean.class); } }
写一个模拟的测试:
package cglib; public class Client { public static void main(String [ ] args) { BookServiceBean service1 = BookServiceFactory.getProxyInstance(new MyCglibProxy("boss")); service1.create(); BookServiceBean service2 = BookServiceFactory.getProxyInstance(new MyCglibProxy("john")); service2.create(); service2.query(); } }
上面的例子,只是在调用方法前输出一句话,实际意义不大。
现在希望只有用户名为boss时才有权限调用方法,否则告诉用户权限不够。
将MyCglibProxy修改如下:
package 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 MyCglibProxy implements MethodInterceptor { public Enhancer enhancer = new Enhancer(); private String name; public MyCglibProxy(String name) { this.name = name; } public Object getDaoBean(Class cls) { enhancer.setSuperclass(cls); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object object, Method method, Object [ ] args, MethodProxy methodProxy) throws Throwable { //用户进行判断 if (!"boss".equals(name) ) { System.out.println("你没有权限!"); return null; } System.out.println("MyCglibProxy is running!"); Object result = methodProxy.invokeSuper(object, args); return result; } }
运行Client发现运行结果已经不同与上次。
现在是boss和所有的人都有query方法的权限,可以将MyCglibProxy再做修改:
@Override public Object intercept(Object object, Method method, Object [ ] args, MethodProxy methodProxy) throws Throwable { //用户进行判断 if (!"boss".equals(name) && !method.getName().equals("query")) { System.out.println("你没有权限!"); return null; } System.out.println("MyCglibProxy is running!"); Object result = methodProxy.invokeSuper(object, args); return result; }