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 对象来设置或获取字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查
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
分享到:
相关推荐
3. 动态方法调用:OGNL支持动态方法调用,允许开发者根据运行时的条件选择调用哪个方法,增加了代码的可扩展性。 4. EL(表达式语言)增强:OGNL作为Struts2的默认EL,提供更丰富的功能,比如可以方便地访问集合、...
OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,主要用在Java...下载“ognl-3.0.6-sources.jar”文件后,开发者可以阅读源码来了解其内部的工作机制,这对于调试、优化或者扩展OGNL的功能大有裨益。
在Eclipse中,你可以将“ognl.jar”作为外部库添加到你的项目中,并通过“Attach Source”功能关联源代码,这样就可以查看和调试OGNL的内部实现,这对于学习、调试或扩展其功能非常有帮助。 OGNL的核心功能包括: ...
通过研究 `ognl-2.7.3-src`,开发者可以深入理解 OGNL 的工作原理,这对于优化应用程序性能、调试 OGNL 相关问题以及扩展 OGNL 功能都大有裨益。同时,对于理解其他类似的表达式语言和框架也有一定的借鉴意义。
3. **OgnlContext类**:ognl的上下文类,继承自`java.util.Map`,扩展了对变量和方法调用的支持。 4. **ASTNode类**:ognl表达式解析后的抽象基类,每个子类对应一种ognl表达式类型,如`ASTProperty`表示属性访问,...
7. **自定义操作符和函数**:OGNL允许用户扩展其表达式语言,自定义操作符和函数,以满足特定需求。 8. **安全问题**:由于OGNL允许动态执行代码,如果不正确地使用,可能会导致代码注入攻击。例如,Struts2曾因...
4. `OgnlContext`:这是OGNL使用的特殊上下文类,它扩展了标准的Java `Map`接口,提供了一些额外的功能,如自动类型转换、变量注册等。 5. `@`符号在OGNL中的使用:在OGNL表达式中,`@`符号用来引用对象。例如,`@...
- 实现自定义的访问器或扩展OGNL的功能。 - 参考Apache Struts2的文档,了解其在实际项目中的应用。 总的来说,研究ognl.jar的源码对于任何想要深入了解Struts2框架以及Java表达式语言的人来说都是一次宝贵的学习...
1. **自定义函数和类型转换器**:源代码会展示如何注册自定义的函数和类型转换器,扩展OGNL的功能。 2. **性能优化**:通过对源码的学习,你可以理解OGNL的执行流程,从而进行针对性的性能优化。 总的来说,研究...
**源码下载**对于开发者来说是至关重要的,它允许我们查看和理解软件的工作原理,调试问题,或者对其进行定制和扩展。在本例中,OGNL的源码可以从官方网站的CVS(Concurrent Versions System)仓库中获取。CVS是一种...
**ognl源码分析** ...通过阅读和理解这些代码,你可以更有效地利用ognl,甚至对其进行扩展或定制以满足特定需求。此外,理解ognl源码也有助于你提升对Java反射、动态语言和表达式解析等领域的理解。
- **自定义扩展**: 可以根据需求实现自定义的类型转换器或扩展OGNL的功能。 **5. 示例分析** 以一个简单的例子说明OGNL的工作原理: ```java Action action = new Action(); action.setName("John"); Map, Object> ...
EL不支持方法调用,但可以与JSTL(JavaServer Pages Standard Tag Library)结合使用,扩展其功能。 3. **主要区别** - **功能范围**:OGNL比EL更强大,它支持更多的操作,如方法调用、数组和集合操作、条件语句...
- **自定义操作符**:用户可以扩展OGNL,定义自己的操作符和函数。 5. **OGNL与Struts2的集成** - 在Struts2中,Action类的属性可以通过OGNL自动绑定到HTTP请求参数,简化了数据处理。 - 视图层的JSP或...
OGNL (Object-Graph Navigation Language) 是一种强大的表达式语言,用于获取和设置Java对象的属性。它在Java开发中广泛应用于数据绑定和表达式计算,尤其是在Spring MVC框架中的视图层,以及许多其他Java应用和框架...
- **自定义函数**:用户可以通过扩展OGNL的方式,自定义函数以满足特定需求。 - **性能优化**:对于频繁使用的表达式,可以考虑使用缓存机制减少重复计算。 ### 总结 OGNL作为Struts2框架的核心技术之一,其强大的...
开发者可以自定义上下文来扩展OGNL的功能。 2. 环境(Environment):环境对象包含当前执行环境的信息,如类加载器、类型转换策略等。 三、OGNL类型转换 1. 自动类型转换:OGNL支持自动类型转换,使得不同类型的...
9. **集成与扩展**:了解OGNL如何与其他框架(如Spring)集成,以及如何自定义函数库或扩展OGNL的行为。 10. **性能优化**:通过阅读源码,开发者可以发现OGNL在设计上的优化策略,比如延迟计算、表达式复用等,这...
7. **自定义转换器和类型拦截器**:可以根据需要扩展OGNL,定义自己的类型转换规则和对象访问策略。 **应用场景** 1. **视图层渲染**:在JSP或FreeMarker模板中,OGNL用来动态地输出数据。 2. **控制器逻辑**:在...