传统IoC容器 battle 轻量级IoC容器

635 阅读5分钟

传统IoC容器

  • Java Bean可以简单的认为是一个POJO

  • 贫血模型User:这个类或者对象只有set/get这种基本的业务操作,不包含复杂的业务操作。贫血模型,是指Model中,仅包含状态(属性),不包含行为(方法)。充血模型,Model 中既包括状态,又包括行为,是最符合面向对象的设计方式。

  • POJO的基本特性:包含Setter/Getter方法

  • Java Beans则称为可写(Writeable)方法/可读(Readable)方法

  • 当一个类定义好后,在运行时,动态地去获取类中的信息(类的信息,方法信息,构造器信息,字段等信息)被称为反射;反射包含四大信息

    1.字段,如id,username ,字段有对应相应的类型

    2.方法,如getId/setId/getUsername/setUsername

    3.构造器,当前使用的是默认构造器,也就是无参构造器

    4.类,User

 public class User {

    //String to Long
    private Long id;//Java Beans中将字段称为Property

    //String to String
    private String username;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "user{" +
                "id=" + id +
                ", username='" + username + '\'' +
                '}';
    }
}

Java Beans作为IoC容器的特性如下:

  1. 依赖查找

  2. 生命周期管理

  3. 配置元信息

    主要是指Java Bean相关的配置元信息,比如反射,以及相关反射所对应的应用。如BeanInfo的PropertyDescriptor.

    • BeanInfo, bean基本信息接口,提供有关bean的方法,属性,事件和其他功能的明确信息
    • BeanDescriptor, 提供有关Bean的整体信息的Bean描述符,例如其显示名称或其定制程序
    • EventSetDescriptor[],定义该bean触发的事件类型的bean的事件描述符
    • PropertyDescriptor[],bean的所有属性的描述符。广泛的应用在Spring框架里, 包含了JavaBean中所说的写方法和读方法,如下所示:
    public class PropertyDescriptor extends FeatureDescriptor {
    	
        private final MethodRef readMethodRef = new MethodRef();
        private final MethodRef writeMethodRef = new MethodRef();
    
        private String writeMethodName;
        private String readMethodName;
    }
    
    BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
    Stream.of(beanInfo.getPropertyDescriptors()).forEach(propertyDescriptor -> {
    	System.out.println("beanInfo.propertyDescriptor = " + propertyDescriptor); 
    });
    
    //弃用Object类中自带的属性
     /**
     * Class<?> stopClass 每个Object都会有一个getClass方法,beanInfo会把这个方法被当作属性来判断,stopClass即停止分析的基类。
     * stopClass或其基类中的任何methodproperties事件都将在分析中被忽略。
     * 对象访问都是通过方法的形式来访问而非字段的形式,getClass会被认为是一个property
     */
    BeanInfo stopBeanInfo = Introspector.getBeanInfo(User.class, Object.class);
    Stream.of(stopBeanInfo.getPropertyDescriptors()).forEach(propertyDescriptor -> {
    	System.out.println("stopBeanInfo.propertyDescriptor = " + propertyDescriptor);
    });
    
    BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
    Stream.of(beanInfo.getPropertyDescriptors()).forEach(propertyDescriptor -> {
    	System.out.println("beanInfo.propertyDescriptor = " + propertyDescriptor);
        //propertyDescriptor,允许添加属性编辑器(PropertyEditor)
        //PropertyEditor所做的内容,就是GUI程序一般会把text(String类型)的内容转换成Property所对应的Type(GUI -> text(String) ->PropertyType)
     	Class propertyType = propertyDescriptor.getPropertyType();
     	String propertyName = propertyDescriptor.getName();
     	//如把属性id进行转换
     	if("id".equals(propertyName)){
            //为id 字段/属性 增加 PropertyEditor
            //bean输入的是一个String类型,但是需要输出为Long类型 Long.valueOf()
            propertyDescriptor.setPropertyEditorClass(StringToLongPropertyEditor.class);
            //创建porpertyEditor
            propertyDescriptor.createPropertyEditor();
    	}
    });
    

    在Spring中一般会把 text(String类型) 转换成相应的类型,这种方法在Spring 3.0之前大量的基于PropertyEditorSupport来进行操作,它既满足元数据或元信息编程,也是一些类型配置和转换的根据。

        /**
         * 进行特定的属性转换一般有两种方式
         * 1. 实现PropertyEditor接口,PropertyEditor类为希望允许用户编辑给定类型的属性值的GUI提供支持
         * 2. 使用PropertyEditorSupport等一些propertyEditor的支持类,
         * PropertyEditorSupport是一个支持类,可帮助构建属性编辑器。它可以用作基类或委托。
         */
        static class StringToLongPropertyEditor extends PropertyEditorSupport {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                Long value = Long.valueOf(text);
                //把属性转为转为long类型后进行临时存储,为后续getValue临时取值使用
                setValue(value);
    
            }
        }
    
  4. 事件

    Spring 事件机制也是基于传统Java的事件机制来的

  5. 自定义

    Java bean的自定义可以对方法或者字段进行补充性的说明,如一些描述性的说明和类型转换

  6. 资源管理

    Spring中的资源管理和Java bean的资源管理也有部分相似

  7. 持久化

    Java beans 可以持久化到本地或者可持久化一些相关的资源,一般情况它会把状态进行临时存储,当容器存储之后又可以进行恢复

规范

以上的特性都是源于以下两个规范

  1. JavaBeans

    Java Beans的原生规范

    • 公共的无参构造器
    • 属性可以通过getsetis(可以替代get,用在布尔型属性上)方法或遵循特定命名规范的其他方法访问
    • 可序列化
  2. BeanContext

    比较复杂,简单的说它主要是管理Bean以及Bean容器之间的相互依赖关系, 包括bean的层次性,双亲委派等等

轻量级IoC容器

特性

  1. 一个可以管理应用程序代码的容器。即容器可以管理代码的运行,如:控制代码的启停
  2. 一个可以快速启动的容器,当然也要根据具体实现来,如果依赖的资源比较多,或者所需功能较为强大,对应的性能、速度方面也会有所下降
  3. 一个不需要任何特殊部署步骤即可在其中部署对象的容器。即容器不需要特殊的配置来进行操作。例如EJB在容器部署的时候需要大量的XML配置文件以及相关的资源进行配合,而Spring Framework则相对较轻。
  4. 一个具有如此轻巧的占地面积和最小的Api的容器可以在各种环境中运行的依赖项。即容器能够达到一些比较轻量级的内存占用以及最小化的API的依赖
  5. 一个容器,它为添加被管理对象设置了标准,使其在部署工作量和性能开销方面特别低,以至于可以部署和管理细粒度对象以及粗粒度对象粒状组件。即容器需要有一些可以管控的渠道,这些渠道可以能帮助我们部署和管理一些细粒度的对象甚至是粗粒度的一些组件,主要是为了达到部署上的效率和相关性能的开销

轻量级容器的好处

  1. 逃避整体式容器,即释放一些所谓的聚式或者单体这样的容器
  2. 最大化代码可重用性,即容器/实现能够进行最大程度的复用
  3. 更大程度面向对象
  4. 更大的产品化
  5. 可测试性更高