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;
}