spring如何实现属性注入?(spring源码了解)

  • 属性注入中,我们做的工作是:
    利用IoC思想,采取属性注入。
    1 为属性添加一个set方法
    2 在xml文件中配置Bean

  • 我们把调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一实现类的依赖。spring就是那个第三方,确切来说,第三方是spring IoC容器。它会根据我们的xml文件来实现注入的吧?

  • 什么是 IoC容器?
    IoC容器相当于一个水桶,水桶最起码的功能就是装水。而我们的IoC容器最起码就是要能放置对象。
    水桶起码要能装水,这是一个基本规范,而我们的IoC容器也有一个基本的功能规范,由BeanFactory接口提供了这么一个规范,定义了spring IoC的基本功能,所有其他IoC容器都要实现这个规范。

  • 了解spring IoC容器的基本规范:BeanFactory
    我们知道BeanFactory定义了IoC容器的基本功能规范,所以,下面我们就从BeanFactory这个最基本的容器定义来进入Spring的IoC容器体系,去了解IoC容器的实现原理。下面来看BeanFactory的源码

public interface BeanFactory {

    /**
     用户使用容器时,可以使用转义符“&”来得到FactoryBean本身
     */
    String FACTORY_BEAN_PREFIX = "&";


    /**
     通过name获取bean
     */
    Object getBean(String name) throws BeansException;

    /**
     
     */
     T getBean(String name, Class requiredType) throws BeansException;

    /**
    
     */
    Object getBean(String name, Object... args) throws BeansException;

    /**
     通过class类型获取bean
     */
     T getBean(Class requiredType) throws BeansException;

    /**
     通过Class类型
     */
     T getBean(Class requiredType, Object... args) throws BeansException;

    /**
    不清楚emm
     */
     ObjectProvider getBeanProvider(Class requiredType);

    /**
   
     */
     ObjectProvider getBeanProvider(ResolvableType requiredType);

    /**
     通过containsBean(String name)能让用户判断容器是否含有指定名字的Bean
     */
    boolean containsBean(String name);

    /**
     判断指定名字的Bean是不是单例
     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     判断指定名字的Bean是不是prototype
     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    /**
     判断指定name的bean是不是特定的Class类型
     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     判断指定name的bean是不是特定的Class类型
     */
    boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     获取bean的class类型
     */
    @Nullable
    Class getType(String name) throws NoSuchBeanDefinitionException;

    /**
     获取名为name的bean的所有别名
     */
    String[] getAliases(String name);

}

这些定义的接口方法勾画出了IoC容器的基本特性,因为BeanFactory接口定义了IoC容器。

  • 接下来我们来看IoC容器如何读取xml文件的配置信息的,来个栗子:

定义一个普通的java对象

public class MyTestBean {
    private String testStr = "testStr";
    public String getTestStr() {
        return testStr;
    }
    public void setTestStr(String testStr) {
        this.testStr = testStr;
    }
}

配置xml文件:




    

读取(重点来了)

import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class BeanFactoryTest {
    @Test
    public void testSimpleLoad() {
        /*
        XmlBeanFactory继承自DefaultListableBeanFactory,在其基础上增加了XMl读取器XmlBeanDefinitionReader(这是个接口吧)
        DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory并实现了ConfigurableListableBeanFactory以及BeanDefinitionRegistry接口
         */
         //这里使用了XmlBeanFactory来获取容器,然后使用容器的getBean方法获得容器的对象
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("analysis2.xml"));
        MyTestBean myTestBean = (MyTestBean)beanFactory.getBean("myTestBean");
        System.out.println(myTestBean.getTestStr());
        System.out.println();

    }
}

测试结果:
spring如何实现属性注入?(spring源码了解)_第1张图片

  • IoC容器XmlBeanFactory工作原理
    来看XmlBeanFactory的源码:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.Resource;

/**
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Chris Beams
 * @since 15 April 2001
 * 2001年就已经出现啦
 */
@Deprecated
@SuppressWarnings({"serial", "all"})
//继承自DefaultListableBeanFactory
public class XmlBeanFactory extends DefaultListableBeanFactory {

    //初始化一个XmlBeanDefinitionReader对象,有了这个Reader对象,那些以XML的方式定义的  BeanDefinition就有了处理的地方。
    private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


    /**
     * 提供了两个构造方法
     */
    public XmlBeanFactory(Resource resource) throws BeansException {
        //调用XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)这个构造方法
        this(resource, null);
    }

    /**
     */
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        //我们可以看到,对这些XML形式的信息的处理实际上是由这个XmlBeanDefini-tionReader来完成的。
        this.reader.loadBeanDefinitions(resource);
    }

}

构造XmlBeanFactory这个IoC容器时,需要指定BeanDefinition的信息来源,而这个信息来源需要封装成Spring中的Resource类来给出。Resource是Spring用来封装IO操作的类。比如,我们的BeanDefinition信息是以xml文件形式存在的,那么可以使用像ClassPathResource res = new ClassPathResource(“beans.xml”);这样具体的ClassPathResource来构造需要的Resource,然后作为构造参数传递给XmlBeanFactory构造函数。这样,IoC容器就可以方便地定位到需要的BeanDefinition信息来对Bean完成容器的初始化和依赖注入过程。

  • 说起来上面都是说的如何构造容器,那容器里装的水(bean)又如何装进去?或者说定义?
    答案是使用BeanDefinition

  • 什么是BeanDefinition?
    在这些Spring提供的基本IoC容器的接口定义和实现的基础上,Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。我们都知道,在计算机的世界里,所有的功能都是建立在用数据对现实进行抽象的基础上完成的。IoC容器是用来管理对象依赖关系的,对IoC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理上完成的。这些BeanDefinition就像是容器里装的水,有了这些基本数据,容器才能够发挥作用。

  • XmlBeanDefinitionReader 做了什么?

你可能感兴趣的:(的先生在学spring)