1. cglib概述: java
code Generation Libary (cglib) ,是一个强大的、高性能、高质量的COde生成类库。它能够在运行期扩展Java类与实现Java接口。 spring
cglib封装了asm,能够在运行期动态生成新的class。 框架
cglib用于AOP,JDK中的proxy必须基于接口,cglib没有这个限制 ide
cglib应用: 函数
以一个实例在简单介绍下cglib的应用。
咱们模拟一个虚拟的场景,关于信息的管理。
1)原始需求是任何人能够操做信息的create,update,delete,query操做。
InfoManager.java--封装对信息的操做
性能
public
class InfoManager {
//
模拟查询操做
public
void query() {
System.out.println("query");
}
//
模拟建立操做
public
void create() {
System.out.println("create");
}
//
模拟更新操做
public
void update() {
System.out.println("update");
}
//
模拟删除操做
public
void delete() {
System.out.println("delete");
}
}
InfoManagerFactory.java
--工厂类
public
class InfoManagerFactory {
private
static InfoManager manger =
new InfoManager();
/**
* 建立原始的InfoManager
*
*
@return
*/
public
static InfoManager getInstance() {
return manger;
}
}
client.java
--供客户端调用
public
class Client {
public
static
void main(String[] args) {
Client c =
new Client();
c.anyonecanManager();
}
/**
* 模拟:没有任何权限要求,任何人均可以操做
*/
public
void anyonecanManager() {
System.out.println("any one can do manager");
InfoManager manager = InfoManagerFactory.getInstance();
doCRUD(manager);
separatorLine();
}
/**
* 对Info作增长/更新/删除/查询操做
*
*
@param
manager
*/
private
void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一个分隔行,用于区分
*/
private
void separatorLine() {
System.out.println("################################");
}
}
至此,没有涉及到cglib的内容,由于需求太简单了,可是接下来,需求发生了改变,要求:
2)只有一个叫“maurice”的用户登陆,才容许对信息进行create,update,delete,query的操做。
怎么办?难道在每一个方法前,都加上一个权限判断吗?这样重复逻辑太多了,因而乎想到了Proxy(代理模式),可是原先的InfoManager也没有实现接口,不能采用jdk的proxy。那么cglib在这边就要隆重登场。
一旦使用cgblig,只须要添加一个MethodInterceptor的类以及修改factory代码就能够实现这个需求。
AuthProxy.java
--权限校验代理类
public
class AuthProxy
implements MethodInterceptor {
private String name;
//
会员登陆名
public AuthProxy(String name) {
this.name = name;
}
/**
* 权限校验,若是会员名为:maurice,则有权限作操做,不然提示没有权限
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
if (!"maurice".equals(
this.name)) {
System.out.println("AuthProxy:you have no permits to do manager!");
return
null;
}
return proxy.invokeSuper(obj, args);
}
public String getName() {
return name;
}
public
void setName(String name) {
this.name = name;
}
}
InfoManagerFactory.java
--代码变更以下:
public
class InfoManagerFactory {
/**
* 建立带有权限检验的InfoManager
*
*
@param
auth
*
@return
*/
public
static InfoManager getAuthInstance(AuthProxy auth) {
Enhancer enhancer =
new Enhancer();
enhancer.setSuperclass(InfoManager.
class);
enhancer.setCallback(auth);
return (InfoManager) enhancer.create();
}
}
client.java
--代码修改以下
public
class Client {
public
static
void main(String[] args) {
Client c =
new Client();
c.haveNoAuthManager();
c.haveAuthManager();
}
/**
* 模拟:登陆会员没有权限
*/
public
void haveNoAuthManager() {
System.out.println("the loginer's name is not maurice,so have no permits do manager

");
InfoManager noAuthManager = InfoManagerFactory.getAuthInstance(
new AuthProxy("maurice1"));
doCRUD(noAuthManager);
separatorLine();
}
/**
* 模拟:登陆会员有权限
*/
public
void haveAuthManager() {
System.out.println("the loginer's name is maurice,so have permits do manager

");
InfoManager authManager = InfoManagerFactory.getAuthInstance(
new AuthProxy("maurice"));
doCRUD(authManager);
separatorLine();
}
/**
* 对Info作增长/更新/删除/查询操做
*
*
@param
manager
*/
private
void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一个分隔行,用于区分
*/
private
void separatorLine() {
System.out.println("################################");
}
}
执行下代码,发现这时client端中已经加上了权限校验。
一样是InfoManager,为何这时能多了权限的判断呢?Factory中
enhancer.create()返回的究竟是什么对象呢?这个疑问将在第三部分CGlib中解释。
这边的代码,实际上是介绍了cglib中的enhancer功能.
到这里,参照上面的代码,就可使用cglib带来的aop功能了。可是为了更多介绍下cglib的功能,模拟需求再次发生变化:
3)因为query功能用户maurice才能使用,招来其余用户的强烈的抱怨,因此权限再次变动,只有create,update,delete,才须要权限保护,query任何人均可以使用。
怎么办?采用AuthProxy,使得InfoManager中的全部方法都被代理,加上了权限的判断。固然,最容易想到的办法,就是在AuthProxy的intercept的方法中再作下判断,若是代理的method是query,不须要权限验证。这么作,能够,可是一旦逻辑比较复杂的时候,intercept这个方法要作的事情会不少,逻辑会异常的复杂。
幸亏,cglib还提供了CallbackFilter。使用CallbackFilter,能够明确代表,被代理的类(InfoManager)中不一样的方法,被哪一个拦截器(interceptor)拦截。
AuthProxyFilter.java
public
class AuthProxyFilter
implements CallbackFilter {
private
static
final
int AUTH_NEED = 0;
private
static
final
int AUTH_NOT_NEED = 1;
/**
* <pre>
* 选择使用的proxy
* 若是调用query函数,则使用第二个proxy
* 不然,使用第一个proxy
* </pre>
*/
@Override
public
int accept(Method method) {
if ("query".equals(method.getName())) {
return AUTH_NOT_NEED;
}
return AUTH_NEED;
}
}
这段代码什么意思?其中的accept方法的意思是说,若是代理的方法是query(),那么使用第二个拦截器去拦截,若是代理的方法不是query(),那么使用第一个拦截器去拦截。因此咱们只要再写一个拦截器,不作权限校验就好了。(其实,cglib中的NoOp.INSTANCE就是一个空的拦截器,只要配置上这个就能够了。)
InfoManagerFactory.java
--代码修改以下:(配置不一样的拦截器和filter)
public
class InfoManagerFactory {
/**
* 建立不一样权限要求的InfoManager
*
*
@param
auth
*
@return
*/
public
static InfoManager getSelectivityAuthInstance(AuthProxy auth) {
Enhancer enhancer =
new Enhancer();
enhancer.setSuperclass(InfoManager.
class);
enhancer.setCallbacks(
new Callback[] { auth, NoOp.INSTANCE });
enhancer.setCallbackFilter(
new AuthProxyFilter());
return (InfoManager) enhancer.create();
}
}
记住:setCallbacks中的拦截器(interceptor)的顺序,必定要和
CallbackFilter里面指定的顺序一致!!切忌。
Client.java
public
class Client {
public
static
void main(String[] args) {
Client c =
new Client();
c.selectivityAuthManager();
}
/**
* 模拟:没有权限的会员,能够做查询操做
*/
public
void selectivityAuthManager() {
System.out.println("the loginer's name is not maurice,so have no permits do manager except do query operator

");
InfoManager authManager = InfoManagerFactory.getSelectivityAuthInstance(
new AuthProxy("maurice1"));
doCRUD(authManager);
separatorLine();
}
/**
* 对Info作增长/更新/删除/查询操做
*
*
@param
manager
*/
private
void doCRUD(InfoManager manager) {
manager.create();
manager.update();
manager.delete();
manager.query();
}
/**
* 加一个分隔行,用于区分
*/
private
void separatorLine() {
System.out.println("################################");
}
}
此时,对于query的权限校验已经被去掉了。
经过一个模拟需求,简单介绍了cglib aop功能的使用。
CGlib应用很是广,在spring,hibernate等框架中,被大量的使用。