zoukankan      html  css  js  c++  java
  • 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

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





  • 相关阅读:
    准备使用 Office 365 中国版--邮箱迁移
    准备使用 Office 365 中国版--域名
    中国版的 Office 365
    了解 Office 365
    MySQL Database on Azure 参数设置
    MySQL Database on Azure 的用户名
    Android NOTE
    从源码看Android中sqlite是怎么通过cursorwindow读DB的
    一个由proguard与fastJson引起的血案
    【转载】淘宝架构框架发展史
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6994511.html
Copyright © 2011-2022 走看看