一、CGLIB简介
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
cglib封装了asm,可以在运行期动态生成新的class。
cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。
二、准备工作
要使用cglib那么有两个jar包是必不可少的,一个是asm.jar,一个是cglib.jar包,在本文中有提供下载。
三、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端中已经加上了权限校验。
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等框架中,被大量的使用。
文章出处:http://www.blogjava.net/stone2083/archive/2008/03/16/186615.html
相关推荐
它通过字节码技术为类创建子类,从而实现对目标类的功能增强。在Java中,由于无法直接继承final类或者重写final方法,CGlib提供了一种解决方案,使得我们能够在运行时动态地扩展或修改类的行为。 CGlib的核心是ASM...
**CGLib库详解** CGLib,全称Code Generation Library,是一个强大的高性能的代码生成库,它在Java世界中被广泛使用,特别是在动态代理和AOP(面向切面编程)领域。这个库允许开发者在运行时动态创建类或者增强已有...
**CGLIB2.2 Jar包详解** CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它被广泛应用于Java世界中的动态代理和字节码操作。CGLIB是基于ASM库来实现的,ASM是一个底层的Java字节码操控和分析...
**CGLIB 3.1 源码详解** CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它在Java运行时能够动态地生成子类,主要用于为Java对象提供代理或者扩展功能。CGLIB是许多Java框架的基础,如Spring ...
CGLIB通过字节码技术生成一个子类来实现代理,因此对类的代理效率较高。CGLIB使用ASM库来生成和转换字节码,其核心类是`net.sf.cglib.proxy.Enhancer`,我们可以设置Enhancer的callback来实现方法拦截。 **...
《Spring框架中的CGLIB库详解》 在Java开发领域,Spring框架以其强大的功能和灵活性深受开发者喜爱。在Spring框架的众多组件中,CGLIB(Code Generation Library)扮演着重要角色,尤其在面向切面编程(AOP)中不可...
Java 动态代理详解与 CGLib 实现 在 Java 中,代理模式是一种设计模式,它允许我们在不修改原有对象的基础上,为对象增加额外的功能。代理模式的核心在于代理类(Proxy)作为真实对象(RealSubject)的替代品,提供...
### Java代理技术详解:JDK代理、CGLIB与AspectJ #### 一、代理模式简介 代理模式是一种常见的设计模式,在《Design Patterns in Java》一书中对其有明确的定义:“代理模式为一个对象提供一个代理,以控制对该...
在这个例子中,当我们调用`targetProxy.doSomething()`时,实际执行的是Cglib生成的子类中的方法,这个方法会在调用`doSomething()`前后执行`MyAdvice`中的`intercept`方法,这就是Cglib代理的工作原理。 总的来说...
新的 UserService 实例 = new UserServiceImpl(); UserService proxyUserService = new UserServiceProxy(userServiceImpl);...了解和掌握动态代理技术对于深入理解 Java 并应用于实际项目开发有着重要的意义。
2. **AOP代理**:Spring支持JDK动态代理和CGLIB代理,用于实现AOP功能,拦截并处理方法调用。 3. **事务管理**:Spring提供声明式和编程式两种事务管理方式,简化了事务处理。 四、使用指南 1. **环境准备**:安装...
CGLIB代理通过字节码技术生成子类来实现代理,因此目标类无需实现接口。 四、应用场景 1. 框架集成:MyBatis、Spring等框架广泛使用动态代理来实现AOP(面向切面编程),如事务管理、日志记录等。 2. 缓存:在调用...
如描述中所示,Spring 2.5.6版本需要包括spring.jar、spring-webmvc.jar、commons-logging.jar和cglib-nodep-2.1_3.jar等。同时,如果你打算结合Hibernate进行持久层操作,还需要引入Hibernate的相关jar包,如...
- **描述**:CGLIB库是基于ASM字节码技术实现的一个高性能、动态代理库。 - **作用**:Hibernate利用CGLIB来实现PO(Plain Old Java Object,普通老式Java对象)字节码的动态生成,用于生成代理类或实现对象状态的...
例如,在Spring AOP框架中,CGLib就是用来生成代理对象的技术之一。 CGLib的工作原理是通过ASM库动态生成字节码,然后利用Java的ClassLoader将这些字节码转换为运行时的类。这个过程通常包括以下步骤: 1. 创建...
Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...
【Java动态代理技术详解】 Java动态代理是Java提供的一种在运行时创建代理对象的技术,它允许我们创建代表其他对象的对象,这些代理对象可以在调用实际方法之前和之后执行额外的操作。这种技术对于实现AOP(面向切...
Hibernate是一款强大的Java持久化框架,它的主要作用是简化数据库操作,通过对象关系映射(ORM)技术将数据库的记录映射为Java对象,使得开发者能够使用面向对象的方式来处理数据库交互,而无需直接编写SQL语句。...