`

Ognl的扩展

 
阅读更多

OGNL提供的扩展方式,见官网:http://commons.apache.org/proper/commons-ognl/developer-guide.html

 

一、PropertyAccessor:提供了对属性赋值和提取属性值的方法。

                             因为不同的类的获取属性值和赋值方式不同,如Map、List、javabean,因此有多个子类,第一个子类对应一种类型。

 

 

PropertyAccessor 类何时加载的:

   OgnlRunTime类中静态代码块,在类加载时调用:

    static {
        PropertyAccessor p = new ArrayPropertyAccessor();

        setPropertyAccessor(Object.class, new ObjectPropertyAccessor());
        setPropertyAccessor(byte[].class, p);
        setPropertyAccessor(short[].class, p);
        setPropertyAccessor(char[].class, p);
        setPropertyAccessor(int[].class, p);
        setPropertyAccessor(long[].class, p);
        setPropertyAccessor(float[].class, p);
        setPropertyAccessor(double[].class, p);
        setPropertyAccessor(Object[].class, p);
        setPropertyAccessor(List.class, new ListPropertyAccessor());
        setPropertyAccessor(Map.class, new MapPropertyAccessor());
        setPropertyAccessor(Set.class, new SetPropertyAccessor());
        setPropertyAccessor(Iterator.class, new IteratorPropertyAccessor());
        setPropertyAccessor(Enumeration.class, new EnumerationPropertyAccessor());
}

 自定义PropertyAccessor 如何让Ognl加载上? 调用OgnlRunTime类中的静态方法:

 

    public static void setPropertyAccessor(Class cls, PropertyAccessor accessor)
    {
        synchronized (_propertyAccessors) {
            _propertyAccessors.put(cls, accessor);
        }
    }

 

二、 MethodAccessor

  用于调用对象的方法,用于支持ognl表达式方法的调用:对象.方法名(参数1,参数2,....)

 


MethodAccessor 类何时加载的:

   OgnlRunTime类中静态代码块,在类加载时调用:

static {
        MethodAccessor ma = new ObjectMethodAccessor();

        setMethodAccessor(Object.class, ma);
        setMethodAccessor(byte[].class, ma);
        setMethodAccessor(short[].class, ma);
        setMethodAccessor(char[].class, ma);
        setMethodAccessor(int[].class, ma);
        setMethodAccessor(long[].class, ma);
        setMethodAccessor(float[].class, ma);
        setMethodAccessor(double[].class, ma);
        setMethodAccessor(Object[].class, ma);
}

 

 

自定义MethodAccessor 如何让Ognl加载上?

 调用OgnlRunTime类中的静态方法:(对Ognl的扩展或覆盖某个Class对应的默认的MethodAccessor)

 

public static void setMethodAccessor(Class cls, MethodAccessor accessor)
    {
        synchronized (_methodAccessors) {
            _methodAccessors.put(cls, accessor);
        }
    }

三、 ElementsAccessor

 对象的遍历,用于支持object.{ ... }表达式语法

 


   ElementsAccessor 是何时加载的?

   OgnlRuntime的静态代码块,在类加载时调用:

 static{
   ElementsAccessor e = new ArrayElementsAccessor();

        setElementsAccessor(Object.class, new ObjectElementsAccessor());
        setElementsAccessor(byte[].class, e);
        setElementsAccessor(short[].class, e);
        setElementsAccessor(char[].class, e);
        setElementsAccessor(int[].class, e);
        setElementsAccessor(long[].class, e);
        setElementsAccessor(float[].class, e);
        setElementsAccessor(double[].class, e);
        setElementsAccessor(Object[].class, e);
        setElementsAccessor(Collection.class, new CollectionElementsAccessor());
        setElementsAccessor(Map.class, new MapElementsAccessor());
        setElementsAccessor(Iterator.class, new IteratorElementsAccessor());
        setElementsAccessor(Enumeration.class, new EnumerationElementsAccessor());
        setElementsAccessor(Number.class, new NumberElementsAccessor());
}

 

  自定义TypeConverter 如何让Ognl加载上?

    调用OgnlRuntime的静态方法:(对Ognl的扩展或覆盖某个Class对应的默认的ElementsAccessor实现)

 public static void setElementsAccessor(Class cls, ElementsAccessor accessor)
    {
        synchronized (_elementsAccessors) {
            _elementsAccessors.put(cls, accessor);
        }
    }

 

 

四、 ClassResolver

 用于类的加载,用于支持静态属性或方法的调用,(@class@method(args)、@class@field )



ClassResolver 类何时加载的:

   OgnlContext 类中定义默认的DefaultClassResolver:

 

public static final ClassResolver DEFAULT_CLASS_RESOLVER = new DefaultClassResolver();
private ClassResolver _classResolver = DEFAULT_CLASS_RESOLVER;
  自定义ClassResolver 如何让Ognl加载上?
 
 调用 OgnlContext 类中的方法(替换了Ognl的默认实现DefaultClassResolver):

  

 public void setClassResolver(ClassResolver value)
    {
        if (value == null) { throw new IllegalArgumentException("cannot set ClassResolver to null"); }
        _classResolver = value;
    }

 

五、 TypeConverter

  类型转换,setValue时将值转换为实际的类型,或getValue时将获取的对象转换为需要的类型

 




 

 

TypeConverter 类何时加载的:

   OgnlContext类中默认的TypeConverter:

 

 public static final TypeConverter DEFAULT_TYPE_CONVERTER = new DefaultTypeConverter();
   private TypeConverter _typeConverter = DEFAULT_TYPE_CONVERTER;
 
自定义TypeConverter 如何让Ognl加载上?
 调用 OgnlContext类中的方法:(替换了Ognl的默认实现DefaultTypeConverter):

 

  public void setTypeConverter(TypeConverter value)
    {
        if (value == null) { throw new IllegalArgumentException("cannot set TypeConverter to null"); }
        _typeConverter = value;
    }
  六、MemberAccess
     java中的java.lang.reflect.Member 是Constructor、Method、Filed的接口,java.lang.reflect.AccessibleObject 是 Constructor、Method、Filed的父类。
 AccessibleObject提供setAccessable(true)方法,实现了对非public的Constructor、Method、Filed的访问能力。
API:
AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查
 boolean isAccessible()
          获取此对象的 accessible 标志的值。
 void

setAccessible(boolean flag)
          将此对象的 accessible 标志设置为指示的布尔值。

 

  
MemberAccess 定义了对于private 、protected、默认包的Memeber(Constructor、Method、Field)是否可以访问。  它的默认实现 DefaultMemeberAccess 是不能访问private 、protected、默认包的Memeber。


 
ognl中对于MemberAccess的调用:
 
   public static Object getFieldValue(OgnlContext context, Object target, String propertyName,
                                       boolean checkAccessAndExistence)
            throws NoSuchFieldException
    {
        Object result = null;
        Field f = getField((target == null) ? null : target.getClass(), propertyName);

        if (checkAccessAndExistence) {
            if ((f == null) || !context.getMemberAccess().isAccessible(context, target, f, propertyName)) {//不可访问就返回NotFound
                result = NotFound;
            }
        }
        if (result == null) {
            if (f == null) {
                throw new NoSuchFieldException(propertyName);
            } else {
                try {
                    Object state = null;

                    if (!Modifier.isStatic(f.getModifiers())) {
                        state = context.getMemberAccess().setup(context, target, f, propertyName);//设置可以访问,并返回状态
                        result = f.get(target);//进行访问
                        context.getMemberAccess().restore(context, target, f, propertyName, state);//恢复访问状态
                    } else
                        throw new NoSuchFieldException(propertyName);

                } catch (IllegalAccessException ex) {
                    throw new NoSuchFieldException(propertyName);
                }
            }
        }
        return result;
    }
 

MemberAccess 类何时加载的:

   OgnlContext类中默认的MemberAccess :

 public static final MemberAccess DEFAULT_MEMBER_ACCESS = new DefaultMemberAccess(false);
      private MemberAccess _memberAccess = DEFAULT_MEMBER_ACCESS;

 自定义MemberAccess如何让Ognl加载上?

 调用 OgnlContext类中的方法:(替换了Ognl的默认实现DefaultMemberAccess):
 public void setMemberAccess(MemberAccess value)
    {
        if (value == null) { throw new IllegalArgumentException("cannot set MemberAccess to null"); }
        _memberAccess = value;
    }
 七、NullHandler
     Ognl表达式链中,获取中间的对象为null,遭成之后的属性或方法调用不了,如user.name,如获取的user为null,那么就无法获取或设置它的name属性,
     NullHandler 提供了一种方式,对于表达式链中间的对象为null时,允许生成一个对象。
   常见的情况是mvc框架中从页面传来的数据user.name值,而当前对象中user为null,这时需要创建一个user对象,才能赋值。 
    
    Ognl的默认实现是ObjectNullHandler,它不做任何处理只是返回null,即不创建对象。
  

 Ognl对NullHandler的调用:
 
 protected Object getValueBody(OgnlContext context, Object source)
            throws OgnlException
    {
        Object property = getProperty(context, source);

        Object result = OgnlRuntime.getProperty(context, source, property);

        if (result == null)
        {
            result = OgnlRuntime.getNullHandler(OgnlRuntime.getTargetClass(source)).nullPropertyValue(context, source, property);
        }

        return result;
    }
 NullHandler是何时被加载的:
   在OgnlRuntime类中静态代码块:(在OgnlRuntime类加载时调用)
 NullHandler nh = new ObjectNullHandler();

        setNullHandler(Object.class, nh);
        setNullHandler(byte[].class, nh);
        setNullHandler(short[].class, nh);
        setNullHandler(char[].class, nh);
        setNullHandler(int[].class, nh);
        setNullHandler(long[].class, nh);
        setNullHandler(float[].class, nh);
        setNullHandler(double[].class, nh);
        setNullHandler(Object[].class, nh);
   
 自定义NullHandler如何让Ognl加载:
 
 public static void setNullHandler(Class cls, NullHandler handler)
    {
        synchronized (_nullHandlers) {
            _nullHandlers.put(cls, handler);
        }
    }
 
  • 大小: 98.2 KB
  • 大小: 43.6 KB
  • 大小: 77.9 KB
  • 大小: 40.9 KB
  • 大小: 34.8 KB
  • 大小: 80.7 KB
  • 大小: 51.5 KB
分享到:
评论

相关推荐

    struts2.0中的ognl

    3. 动态方法调用:OGNL支持动态方法调用,允许开发者根据运行时的条件选择调用哪个方法,增加了代码的可扩展性。 4. EL(表达式语言)增强:OGNL作为Struts2的默认EL,提供更丰富的功能,比如可以方便地访问集合、...

    ognl的jar包

    OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,主要用在Java...下载“ognl-3.0.6-sources.jar”文件后,开发者可以阅读源码来了解其内部的工作机制,这对于调试、优化或者扩展OGNL的功能大有裨益。

    ognl.jar(ognl-2.6.11.jar)

    在Eclipse中,你可以将“ognl.jar”作为外部库添加到你的项目中,并通过“Attach Source”功能关联源代码,这样就可以查看和调试OGNL的内部实现,这对于学习、调试或扩展其功能非常有帮助。 OGNL的核心功能包括: ...

    ognl-2.7.3-src

    通过研究 `ognl-2.7.3-src`,开发者可以深入理解 OGNL 的工作原理,这对于优化应用程序性能、调试 OGNL 相关问题以及扩展 OGNL 功能都大有裨益。同时,对于理解其他类似的表达式语言和框架也有一定的借鉴意义。

    ognl源代码以及api文档

    3. **OgnlContext类**:ognl的上下文类,继承自`java.util.Map`,扩展了对变量和方法调用的支持。 4. **ASTNode类**:ognl表达式解析后的抽象基类,每个子类对应一种ognl表达式类型,如`ASTProperty`表示属性访问,...

    ognl源码

    7. **自定义操作符和函数**:OGNL允许用户扩展其表达式语言,自定义操作符和函数,以满足特定需求。 8. **安全问题**:由于OGNL允许动态执行代码,如果不正确地使用,可能会导致代码注入攻击。例如,Struts2曾因...

    OGNL静态方法定义

    4. `OgnlContext`:这是OGNL使用的特殊上下文类,它扩展了标准的Java `Map`接口,提供了一些额外的功能,如自动类型转换、变量注册等。 5. `@`符号在OGNL中的使用:在OGNL表达式中,`@`符号用来引用对象。例如,`@...

    ognl jar包源码

    - 实现自定义的访问器或扩展OGNL的功能。 - 参考Apache Struts2的文档,了解其在实际项目中的应用。 总的来说,研究ognl.jar的源码对于任何想要深入了解Struts2框架以及Java表达式语言的人来说都是一次宝贵的学习...

    ognl2.7.3源代码

    1. **自定义函数和类型转换器**:源代码会展示如何注册自定义的函数和类型转换器,扩展OGNL的功能。 2. **性能优化**:通过对源码的学习,你可以理解OGNL的执行流程,从而进行针对性的性能优化。 总的来说,研究...

    ognl官网下载源码

    **源码下载**对于开发者来说是至关重要的,它允许我们查看和理解软件的工作原理,调试问题,或者对其进行定制和扩展。在本例中,OGNL的源码可以从官方网站的CVS(Concurrent Versions System)仓库中获取。CVS是一种...

    ognl源码 下载

    **ognl源码分析** ...通过阅读和理解这些代码,你可以更有效地利用ognl,甚至对其进行扩展或定制以满足特定需求。此外,理解ognl源码也有助于你提升对Java反射、动态语言和表达式解析等领域的理解。

    ognl-2.6.11.jar源码

    - **自定义扩展**: 可以根据需求实现自定义的类型转换器或扩展OGNL的功能。 **5. 示例分析** 以一个简单的例子说明OGNL的工作原理: ```java Action action = new Action(); action.setName("John"); Map, Object> ...

    ognl和el区别

    EL不支持方法调用,但可以与JSTL(JavaServer Pages Standard Tag Library)结合使用,扩展其功能。 3. **主要区别** - **功能范围**:OGNL比EL更强大,它支持更多的操作,如方法调用、数组和集合操作、条件语句...

    ognl的源码

    - **自定义操作符**:用户可以扩展OGNL,定义自己的操作符和函数。 5. **OGNL与Struts2的集成** - 在Struts2中,Action类的属性可以通过OGNL自动绑定到HTTP请求参数,简化了数据处理。 - 视图层的JSP或...

    ognl API文档

    OGNL (Object-Graph Navigation Language) 是一种强大的表达式语言,用于获取和设置Java对象的属性。它在Java开发中广泛应用于数据绑定和表达式计算,尤其是在Spring MVC框架中的视图层,以及许多其他Java应用和框架...

    struts2 ognl的用法

    - **自定义函数**:用户可以通过扩展OGNL的方式,自定义函数以满足特定需求。 - **性能优化**:对于频繁使用的表达式,可以考虑使用缓存机制减少重复计算。 ### 总结 OGNL作为Struts2框架的核心技术之一,其强大的...

    OGNL API文档

    开发者可以自定义上下文来扩展OGNL的功能。 2. 环境(Environment):环境对象包含当前执行环境的信息,如类加载器、类型转换策略等。 三、OGNL类型转换 1. 自动类型转换:OGNL支持自动类型转换,使得不同类型的...

    ognl源代码(可以省去不少麻烦)

    9. **集成与扩展**:了解OGNL如何与其他框架(如Spring)集成,以及如何自定义函数库或扩展OGNL的行为。 10. **性能优化**:通过阅读源码,开发者可以发现OGNL在设计上的优化策略,比如延迟计算、表达式复用等,这...

    ognl表达式

    7. **自定义转换器和类型拦截器**:可以根据需要扩展OGNL,定义自己的类型转换规则和对象访问策略。 **应用场景** 1. **视图层渲染**:在JSP或FreeMarker模板中,OGNL用来动态地输出数据。 2. **控制器逻辑**:在...

Global site tag (gtag.js) - Google Analytics