java 内省机制_Java Beans内省机制以及在Spring中的应用

1. 企业级Beans

EJB就像共产主义,听说过,没见过

EJB3.1以后是嵌入式的

RPC

有状态Bean和无状态Bean

JPA

持久化Bean

JMS

消息Bean

2. Java Beans内省机制

2.1 Bean基础

充血模型和贫血模型

充血模型:包括了一些状态和具体的业务操作

贫血模型:只有setter和getter

状态Bean

Session Bean

JSF:除了页面上的操作,还需要管理Session(Session Bean)

状态Bean:比如有个远程服务

2.2 Java反射

获取Class信息

构造器(Constructor)

方法(Method)

字段(Field)

2.3 内省

2.3.1 概念

获取Java BeanInfo,Bean的描述针对的是某个类的

类(模版)没有状态,因为类定义好了以后就是字节码,固定了,而实例(Bean)是有状态的。

Bean描述符(BeanDescriptor):不只是Bean的描述,

方法描述符(MethodDescriptor)

字段描述符(FieldDecriptor)

2.3.2 BeanDescriptor

public class BeanDescriptor extends FeatureDescriptor {

private Reference extends Class>> beanClassRef;

private Reference extends Class>> customizerClassRef;

}

2.3.3 MethodDescriptor

Java MethodDescriptor实现:

public class MethodDescriptor extends FeatureDescriptor {

private final MethodRef methodRef = new MethodRef();

....

}

final class MethodRef {

private String signature;

private SoftReference methodRef;

private WeakReference> typeRef;

.....

}

上述代码说明:

BeanInfo 对象不是单例,是多例。

Class很多时候是单例的。

弱引用(WeakReference):常当作缓存,不用的时候可以马上让GC收回(其中保存的对象实例可以被GC回收掉)。Class实例暂存于一个由WeakReference构成的Map中作为Cache。

软引用(SoftReference):强引用,它保存的对象实例,除非JVM即将OutOfMemory,否则不会被GC回收。这个特性使得它特别适合设计对象Cache。对于Cache,我们希望被缓存的对象最好始终常驻内存,但是如果JVM内存吃紧,为了不发生OutOfMemoryError导致系统崩溃,必要的时候也允许JVM回收Cache的内存,待后续合适的时机再把数据重新Load到Cache中。这样可以系统设计得更具弹性。

setter和getter并不是需要成对出现

2.3.4 PropertyDescriptor

Java PropertyDescriptor实现

public class PropertyDescriptor extends FeatureDescriptor {

private Reference extends Class>> propertyTypeRef;

private final MethodRef readMethodRef = new MethodRef();

private final MethodRef writeMethodRef = new MethodRef();

private Reference extends Class>> propertyEditorClassRef;

.....

}

readMethodRef和writeMethodRef可以任意为空,但是不会同时为空,因为判断一个property的时候,我们必须根据setter和getter来判断。

3. Java Beans事件监听

3.1 属性变化概念

3.1.1 属性变化监听器PropertyChangeListener

传递了一个字符串(Text)类型

传递值转化成对应的数据类型,并且赋值

对应事件发生(不同属性对应的事件处理可能不同)

3.1.2 属性变化事件PropertyChangeEvent

事件源(Source)

属性名称(PropertyName)

变化前值(OldValue)

变化后值(NewValue)

3.2 属性事件监听源码解析

对每个对象的属性进行设值的过程需要自定义Editor类,继承自

java.beans.PropertyEditorSupport

在Spring中,有很多已定义的各种Editor,比如CharsetEditor等,比如:

public class CharsetEditor extends PropertyEditorSupport {

@Override

public void setAsText(String text) throws IllegalArgumentException {

if (StringUtils.hasText(text)) {

setValue(Charset.forName(text));

}

else {

setValue(null);

}

}

....

}

通过以上代码可知,他统一把传入的文本值text通过setValue方法转化为相应类型的值了。setValue实现如下:

java.beans.PropertyEditorSupport#setValue

/**

* Set (or change) the object that is to be edited.

*

* @param value The new target object to be edited. Note that this

* object should not be modified by the PropertyEditor, rather

* the PropertyEditor should create a new object to hold any

* modified value.

*/

public void setValue(Object value) {

this.value = value;

firePropertyChange();

}

由上可知,它不仅是自己进行了设值操作,并且触发了一个方法

java.beans.PropertyEditorSupport#firePropertyChange

实现如下:

/**

* Report that we have been modified to any interested listeners.

*/

public void firePropertyChange() {

java.util.Vector targets;

synchronized (this) {

if (listeners == null) {

return;

}

targets = unsafeClone(listeners);

}

// Tell our listeners that "everything" has changed.

PropertyChangeEvent evt = new PropertyChangeEvent(source, null, null, null);

for (int i = 0; i < targets.size(); i++) {

PropertyChangeListener target = targets.elementAt(i);

target.propertyChange(evt);

}

}

说明我们需要设置属性值的时候,不仅需要定义PropertyEditorSupport的子类,然后通过java.beans.PropertyDescriptor#setPropertyEditorClass方法设值,还需要定义事件监听器,实现PropertyChangeListener,通过事件回调的方式实现属性值的设置。实现如下:

private static class SetPropertyChangeListener implements PropertyChangeListener {

private final Object bean;

private final Method setterMethod;

private SetPropertyChangeListener(Object bean, Method setterMethod) {

this.setterMethod = setterMethod;

this.bean = bean;

}

@Override

public void propertyChange(PropertyChangeEvent event) {

//事件源

PropertyEditor source = (PropertyEditor) event.getSource();

try {

setterMethod.invoke(bean, source.getValue());

} catch (Exception e) {

}

}

}

以上代码中的事件源,根据java.beans.PropertyEditorSupport的构造方法得知,事件源对象就是实现PropertyEditorSupport的子类对象。所以source.getValue()对应的值就是org.springframework.beans.propertyeditors.CharsetEditor#setAsText方法参数text对应的值了。这样就全部串起来了。

/**

* Constructs a PropertyEditorSupport object.

*

* @since 1.5

*/

public PropertyEditorSupport() {

setSource(this);

}

4. Spring Beans属性处理

属性修改器(PropertyEditor)

属性修改器注册(PropertyEditorRegistry)

PropertyEditor注册器(PropertyEditorRegistrar)

public class MyPropertyEditorRegistrar implements PropertyEditorRegistrar {

@Override

public void registerCustomEditors(PropertyEditorRegistry registry) {

// 将Date 类型 date 字段设置 PropertyEditor

registry.registerCustomEditor(Date.class,"date",new DatePropertyEditor());

}

}

自定义PropertyEditor配置器(CustomEditorConfigurer)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值