实习成长之路: 重新认识IOC,你可能对IoC有些误会?

极客时间:小马哥学习笔记

IoC主要实现策略:面试官总问IoC和DI的区别,他真的理解吗?

Ioc的主要实现策略

  1. 服务定位模式。通常是通过JNDI这种技术获取JavaEE的组件
  2. 依赖注入
  3. 上下文依赖查询
  4. 模板方法
  5. 策略模式(不太深入)
    可以说就是依赖查找和依赖注入

IoC容器的职责:IoC除了依赖注入,还涵盖哪些职责呢?

  • 实现与执行任务之间的解耦
  • 关注设计上的最终目标,而不是它具体的实现
  • 释放这个模块
  • 模块取消,(比如依赖变更了,如果是同步调用,影响比较明显,但是用IOC的话,可能影响不是很明显)

白话文职责

  • 通用职责
  • 依赖处理
    - 依赖查找
    - 依赖注入
  • 生命周期管理
    - 容器
    - 托管的资源(Java Beans 或其他资源)
  • 配置
    - 容器
    - 外部化配置
    - 托管的资源

IoC容器的实现

在这里插入图片描述

传统IoC容器实现:JavaBeans也是IoC容器吗?

在这里插入图片描述

传统JavaBeans实现

贫血模型、只有可写方法、可读方法、默认构造参数

public class Person {
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 名字
     */
    private String name;

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

获取JavaBeans元信息

public class BeanInfoDemo {

    public static void main(String[] args) throws IntrospectionException {
        //Java自省的方式来操作
        BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
        Stream.of(beanInfo.getPropertyDescriptors())
            .forEach(propertyDescriptor -> {
                System.out.println(propertyDescriptor.toString());
            });
    }
}

结果

java.beans.PropertyDescriptor[name=age; propertyType=class java.lang.Integer; readMethod=public java.lang.Integer ioc.eg1.Person.getAge(); writeMethod=public void ioc.eg1.Person.setAge(java.lang.Integer)]
java.beans.PropertyDescriptor[name=class; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]
java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String ioc.eg1.Person.getName(); writeMethod=public void ioc.eg1.Person.setName(java.lang.String)]

为什么会 获取这些信息?
先来看看BeanInfo源码里面有什么

public interface BeanInfo {
	//Bean的描述信息
	BeanDescriptor getBeanDescriptor();
	//Bean事件的描述信息
	EventSetDescriptor[] getEventSetDescriptors();
	//Bean的字段信息
	PropertyDescriptor[] getPropertyDescriptors();

这里我们获取了Person的字段元信息,但是为什么多了一个class字段呢?
因为每个Object都有一个可读方法getClass(),然后就会把它当成一个默认属性,误以为是一个property
所以上面就会多出来一个属性class,并且他只有一个读方法
想要关掉它,就多传一个参数

BeanInfo beanInfo = Introspector.getBeanInfo(Person.class,Object.class);

这个第二个参数就是父类,防止多层次的类都打印出来,这个参数就是stopClass

那我们的类型转换元信息转换怎么做的

public class BeanInfoDemo {

    public static void main(String[] args) throws IntrospectionException {
        //Java自省的方式来操作
        BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
        Stream.of(beanInfo.getPropertyDescriptors())
            .forEach(propertyDescriptor -> {
                //PropetyDescriptor允许添加属性编辑器  -  PropertyEditor
                //我们以往的GUI程序都会 text(String) -->  PropertyType
                //Spring怎么做类型转换的
                //Person  name -> String
                //          age ->Integer
                Class<?> propertyType = propertyDescriptor.getPropertyType();
                String propertyName = propertyDescriptor.getName();
                if("age".equals(propertyName)){
                    //为"age" 字段/属性增加 PropertyEditor
                    //输入一个String类型,输出一个Integer类型
                    //其实很简单就是Integer.valueOf();
                    //具体怎么操作
                    //1.写自己的PropertyEditor的实现
                    //2.关联起来
                    //3.将我们的Bean放进去,创建出来
                    propertyDescriptor.setPropertyEditorClass(StringToIntegerPropertyEditor.class);
                    propertyDescriptor.createPropertyEditor(Person.class);
                }
            });
    }
    static class StringToIntegerPropertyEditor extends PropertyEditorSupport {
        //方法拦截
        @Override
        public void setAsText(String text){
            Integer value = Integer.valueOf(text);
            setValue(value);
        }
    }

}

PropertyEditorSupport


public class PropertyEditorSupport implements PropertyEditor {
    public void setValue(Object value) {
        this.value = value;
        firePropertyChange();
    }

    /**
     * Gets the value of the property.
     *
     * @return The value of the property.
     */
    public Object getValue() {
        return value;
    }
      public String getAsText() {
        return (this.value != null)
                ? this.value.toString()
                : null;
    }

    /**
     * Sets the property value by parsing a given String.  May raise
     * java.lang.IllegalArgumentException if either the String is
     * badly formatted or if this kind of property can't be expressed
     * as text.
     *
     * @param text  The string to be parsed.
     */
    public void setAsText(String text) throws java.lang.IllegalArgumentException {
        if (value instanceof String) {
            setValue(text);
            return;
        }
        throw new java.lang.IllegalArgumentException(text);
    }

我理解的就是Spring再做一个Bean的元信息、类型转换的时候,接收进来的都是String,然后在其他实现类里重写这个方法,将它转换成我们Bean定义的Type,就像上面的String—>Integer方法一样

Spring3.0以前,大量的类型转换实践都是基于PropertyEditorSupport来做的,上面的几个操作,基本满足于我们的元数据或元信息编程,他也就是一些类型配置和转换的一些根据

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会写代码的花城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值