CGlib小记

CGlib是一个强大的代码生成包,常被用于各种AOP框架,提供“拦截”功能。JDK本身就为控制要访问的对象提供了一种途径,动态代理Proxy。但是被代理的累必须实现一个或多个接口。如果想摆脱这个限制,为没有实现接口的类代理的话,可以使用CGlib。

下面是一个入门学习的小例子。

需求:InfoManager类有四个方法,query、del、create、update。要对这些方法进行访问控制。只有end用户可

以访问所有方法,而其他用户只能query。

<span style="font-size:18px;">public class InfoManager
{
	public void query()
	{
		System.out.println("query method...");
	}

	public void del()
	{
		System.out.println("del method...");
	}

	public void create()
	{
		System.out.println("create method...");
	}

	public void update()
	{
		System.out.println("update method...");
	}
}
</span>

InfoManagerFactory类,用来生成InfoManager实例。

<span style="font-size:18px;">public class InfoManagerFactory
{
	public static InfoManager getInstance(UserProxy proxy)
	{
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(InfoManager.class);//被代理的类
		enhancer.setCallbacks(new Callback[]{proxy, NoOp.INSTANCE});//两个callBack,第二个实则为空限制,实现某些方法的无限制访问
		enhancer.setCallbackFilter(new UserProxyFilter());//CallBack过滤器
		return (InfoManager) enhancer.create();//创建带有拦截过滤功能的InfoManager的子类实例
	}
}
</span>

UserProxy实现MethodInterceptor接口,用来拦截。

<span style="font-size:18px;">public class UserProxy implements MethodInterceptor
{
	private String name;

	public UserProxy(String name)
	{
		super();
		this.name = name;
	}

	@Override
	public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable
	{
		if(!"end".equals(this.name))//非end用户,不能访问
		{
			System.out.println(name + "没有权限访问方法:" + method.getName());
			return null;
		}
		return proxy.invokeSuper(object, args);//通过拦截,则反射调用InfoManager的对应方法。
	}

}</span>

UserProxyFilter实现CallbackFilter,制定规则,决定采用前面的哪个CallBack。

<span style="font-size:18px;">public class UserProxyFilter implements CallbackFilter
{
	public static final int USER_NEED = 0;

	public static final int USER_NOT_NEED = 1;

	@Override
	public int accept(Method method)
	{
		if("query".equals(method.getName()))
		{
			return USER_NOT_NEED;
		}
		return USER_NEED;
	}

}
</span>

这里要解释一下,accept方法返回值是int,就是这个值决定了采用哪个拦截器。看之前的这句代码:

<span style="font-size:18px;"><span style="font-size:18px;">enhancer.setCallbacks(new Callback[]{proxy, NoOp.INSTANCE});</span></span>

Enhancer设置了一个callBack数组,第一个为我们写的用户权限的拦截器,第二个为一个空的拦截器。当accept方法

发现被用户操作调用的方法是query时,应该都允许,所以返回值是1,所以采用了callBack数组下标为1的拦截器:空

拦截器,不进行验证拦截;当用户操作调用的方法是不query时,需要验证用户权限进行拦截,所以返回值是0,采用

callBack数组下标为0的拦截器:UserProxy。而UserProxy中,我们只允许end用户访问InfoManager类方法。至此,

我们就实现了需求中的功能。

InfoManagerFactory中,我们看到创建实例的方法中用到了Enhance,最后return了enhancer.create()的返回值。那么

在设置了各种属性后,enhancer.create()到底做了什么呢,使得InfoManager实例,按照我们的规则被调用和拒绝。

在文章最开始,我们说到CGlib是一个动态生成代码的包,上面的小例子,原理其实是这样的:cglib在代码运行期间

,根据UserProxyFilter的accept方法返回值,选择了相应的MethodInterceptor拦截器。然后动态生成了一个InfoMana

ger的子类,并在子类中覆写了InfoManager中的各个方法,去调用拦截器的intercept方法。所以,Factory得到是cglib

生成的子类,调用里面的方法时,都会去拦截器里进行验证。

CGlib小记

时间: 2024-10-25 03:42:26

CGlib小记的相关文章

SPring+Structs2实现的项目中进行Spring AOP时的相关小记

 SPring+Structs2实现的项目中进行Spring AOP时的相关小记 1.一般为了方便开发Structs2的项目中的action都会建立一个BaseAction如果继承了BaseAction中的子类进行AOP时,只能指定AOP中的PointCut为BaseAction 如果对应的BaseAction如果继承于ActionSupport的话,就只能定义AOP中的PointCut为ActionSupport了 因为Spring生成的代理类中,对同名的方法,只有一个,即子类重写父类的方

SpringBoot - 二零一七0421小记

一.SpringBoot使用起来比起SpringMVC更便捷,在注解上的小变化,我记录了下面几个: @Controller + @ResponseBody = SpringMVC中用@RestController来代替前面两个注解,通过这个注解,可以将所有的前端http请求放入SpringBoot的Controller容器中,并返回json格式的数据给前端 @RequestMapping(value={"/hello","/hi"},method=RequestMe

Spring框架_代理模式(静态代理,动态代理,cglib代理)

共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                                      用户库jar包,需要手动发布到tomcat. (每次新建项目) 3) 重新发布项目 * 配置文件错误 (web.xml / struts.xml /bean.xml /hibernate.xml / *.hbm.xml) 明确的提示 * 端口占用 * we

广州postgresql用户会技术交流会小记 2015-9-19

广州postgresql用户会技术交流会小记  2015-9-19 今天去了广州postgresql用户会组织的技术交流会 分别有两个session 第一个讲师介绍了他公司使用postgresql -X2的情况 第二个讲师介绍了postgresql里面的一些执行计划分析 我个人比较关注第一个session,因为涉及到真正的应用案例 网上有对postgresql -X2的简短介绍,我先转载过来 转载:http://francs3.blog.163.com/blog/static/405767272

Java进阶之 JDK动态代理与Cglib动态代理

一.动态代理概述: 与静态代理对照(关于静态代理的介绍 可以阅读上一篇:JAVA设计模式之 代理模式[Proxy Pattern]), 动态代理类的字节码是在程序运行时由Java反射机制动态生成. 注意: 1.AspectJ是采用编译时生成AOP代理类,具有更好的性能,但是需要使用特定的编译器进行处理 2.Spring AOP采用运行时生成AOP代理类,无需使用特定编译器进行处理,但是性能相对于AspectJ较差 二.JDK动态代理 [对有实现接口的对象做代理] 1.JDK动态代理中 需要了解的

java动态代理和cglib动态代理

动态代理应用广泛,Spring,Struts等框架很多功能是通过动态代理,或者进一步封装来实现的. 常见的动态代理模式实现有Java API提供的动态代理和第三方开源类库CGLIB动态代理. Java API提供的动态代理是基于类反射实现的,用到的类有: java.lang.reflect.InvocationHandler; java.lang.reflect.Method; java.lang.reflect.Proxy; 其实现是通过Proxy类的newProxyInstance()方法产

git 学习小记之记住https方式推送密码

昨天刚刚学了点git基础操作,但是不幸的是[email protected]给出公告说尽量使用 https 进行操作.可是在用 https 进行 push 时,都需要输入帐号和密码. 各种百度谷歌之后在[email protected]官网找到了解决方法<https方式使用[email protected]设置密码的方式>文中给出了几个方法,并且都非常简单. 关于 cache 缓存方式,我不太喜欢,因为要设置时间,而且会过期.而 store 相应的非常方便,设置全局后,方便多个库使用.当然如果

关于自动化部署之docker容器的折腾小记

docker的英文本意是码头工人,也就是搬运工,这种搬运工搬运的是集装箱(Container),集装箱里面装的可不是商品货物,而是任意类型的App,Docker把App(叫Payload)装在Container内,通过Linux Container技术的包装将App变成一种标准化的.可移植的.自管理的组件,这种组件可以在你的latop上开发.调试.运行,最终非常方便和一致地运行在production环境下. 具体什么是docker,你们自己找资料吧,应该好理解.   可以说是个运维的利器,可以把

安卓环境搭建小记

安装容易出现问题:1.更新sdk时可能无法连接服务器,可在C:\WINDOWS\system32\drivers\etc下的hosts文件最后添加:#Google主页203.208.46.146 www.google.com#这行是为了方便打开Android开发官网 现在好像不翻墙也可以打开74.125.113.121 developer.android.com#更新的内容从以下地址下载203.208.46.146 dl.google.com203.208.46.146 dl-ssl.googl