Spring-IOC

Spring-IOC

一、什么是IOC?

  • Ioc即Inverse of Control,中文为控制反转。
  • 在Spring中,创建对象的工作不再由应用程序(程序员主动的使用new关键字)主动完成,而是由Spring容器负责创建,然后注入给应用程序,由Spring来管理应用程序中的所有对象及其依赖关系。
  • 通俗说就是程序员在代码中无需使用new关键字来创建对象,创建对象的任务交给了Spring。然后Spring根据xml中配置的属性,将其注入到对象中。(创建对象并赋值

二. 实例化 Spring IoC 容器

Spring 核心容器的理论很简单:Spring 核心容器就是一个超级大工厂,所有的对象都会被当成 Spring 核心容器管理的对象

你必须实例化 Spring IoC 容器,读取其配置文件来创建 Bean 实例。然后你可以从 Spring IoC 容器中得到可用的 Bean 实例。

BeanFactory
└── ApplicationContext
    └── ClassPathXmlApplicationContext

Spring IoC 容器主要是基于 BeanFactoryApplicationContext 两个接口:

  • BeanFactory 是 Spring IoC 容器的顶层接口
  • ApplicationContext 是最常用接口
  • ClassPathXmlApplicationContext 是 ApplicationContext 的实现类。顾名思义,它从 classpath 中加载一个 XML 配置文件,构建一个应用程序上下文。你也可以指定多个配置文件。

BeanFactory 接口定义了 Spring IoC 整个体系中中最重要的方法(簇):getBean() 方法。这个方法用于从 Spring IoC 容器中获得 Bean 。

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("service.xml", "dao.xml");

在获得应用程序上下文(也就是IoC容器)后,你只需要调用 getBean() 方法并传入唯一的 Bean ID/名称和 Bean 的 Class 对象,就可以获得容器中的 Bean。

Human tom = context.getBean("tom", Human.class);

三、Spring创建Bean

Spring可以帮你创建、管理Bean对象,但你需要“告诉”它要创建、管理哪些对象。

Spring允许你在一个(或者多个)xml配置文件中配置Bean,对于Spring容器,这些个配置文件就是它创建Bean对象的依据。

一个Spring xml的基本配置样式是:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

多个Spring xml文件我们可以通过import标签进行导入,和多为一:

<import resource="spring-dao.xml"/>

创建 Bean 的方式常见三种:

  • 类自身的构造方法
  • 工厂类提供的工厂方法
  • 工厂对象提供的工厂方法

1、使用类自身的构造方法

每个 bean 都必须提供一个唯一的名称或id,以及一个完全限定的类名,用来让 Spring IoC 容器对其进行创建。Spring 通过类的构造方法来创建 Bean 对象。

<beans ...>
    <bean id="xxx" class="xxx.xxx.Xxx"></bean>
</beans>

2、 使用工厂类提供的工厂方法

<bean id="tom" class="工厂类" factory-method="工厂方法">
</bean>

3、 使用工厂对象提供的工厂方法

<!-- 声明创建工厂对象 -->
<bean id="factory" class="工厂类"/>

<bean id="tom" factory-bean="工厂对象id" factory-method="工厂方法">
</bean>

四、Spring装配简单属性

装配,即为 Bean 的属性进行 初始化 / 赋值。

简单类型 是指: 基本数据类型、基本数据类型包装类 和 字符串 。

装配方式有两种:

  • 通过 构造方法 装配
  • 通过 setter 装配

1、 构造方法装配

通过构造方法装配,即设置 Spring 通过调用有参构造方法(默认是调用无参构造方法)来创建对象。在 bean 元素内使用 constructor-arg 子元素,即可触发构造方法装配。

<bean id="..." class="...">
    <constructor-arg index="x" value="xx"/>
    ...
</bean>

index 属性表示构造函数形参 索引(从0开始)。如果参数的类型具有唯一性,那么可以使用 type 属性,通过 参数类型 来指定构造方法和参数值。

为了简化配置,Spring 提供了一个名为 c 的 schema,来简化配置。

<beans xmlns="..."
       xmlns:xsi="..."
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="...">

    <bean id="..." class="..." c:_0="xxx" c:_1="xxx" ... />
</beans>

使用这种简写方式,完全不用出现 costructor-arg 子元素,只需在 bean 元素中多增加几个 c:_索引="参数值" 这样的属性。

2、 setter 装配

通过 setter 装配,即设置 Spring 在(通过无参构造方法)创建对象后,通过调用对象的属性的 setter 方法来为对象的属性赋值。在 bean 元素内使用 property 子元素,即可触发 setter 装配。

<bean id="..." class="...">
    <property name="xxx" value="xxx" />
    ...
</bean>

property 元素的 name 属性用于指定对象的属性名,value 属性用于指定要设置值。

为了简化配置,Spring 提供了一个名为 p 的 schema,来简化配置。

<beans xmlns="..."
       xmlns:xsi="..."
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="...">

    <bean id="tom" class="com.hemiao.bean.Human" p:name="tom" p:age="20" />

    ...
</beans>

使用这种简写方式,完全不用出现 property 子元素,只需在 bean 元素中多增加几个 p:属性名="属性值" 这样的属性。

五、Spring装配复杂属性

更复杂的属性类型是集合类型(数组、List、Set、Map)属性。

Bean 的属性可能远不止基本类型这么简单,还有可能是基本类型的集合(List、Set 和 Map)。这种情况下,属性的赋值不再是 property-value 这种结构,而是 property-list-value 三层结构。

<bean id="..." class="...">

    <property name="数组属性名">
        <array>
            <value>xxx</value>
            ...
        </array>
    </property>

    <property name="List属性名">
        <list>
            <value>xxx</value>
            ...
        </list>
    </property>

    <property name="Set属性名">
        <set>
            <value>xxx</value>
            ...
        </set>
    </property>

    <property name="Map属性名">
        <map>
            <entry key="xxx" value="xx"/>
            ...
        </map>
    </property>

</bean>

如果集合是引用类型的集合,那么使用的子元素就从 value 改为 ref。map 使用的是 key-refvalue-ref

<list>
    <ref bean="myDataSource" />
</list>

<set>
    <ref bean="myDataSource" />
</set>

<map>
    <entry key ="a ref" value-ref="myDataSource"/>
</map>

引用的集合还有一种简写形式

<list>
    <ref class="类的完全限定名" />
</list>

<set>
    <ref class="类的完全限定名" />
</set>

<map>
    <entry key ="a ref" class="类的完全限定名"/>
</map>

六、 自动装配

当一个 Bean 需要访问另一个 Bean 时,你可以显示指定引用装配它。不过,Spring IoC 容器提供自动装配功能,只需要在 beanautowire 属性中指定自动装配模式就可以了。

装配模式 说明
no 默认值。不执行自动装配。你必须显示地装配所依赖对象
byName 以 Bean 的属性名为依据,装配一个与属性名同名的 Bean
byType 以 Bean 的属性类型为依据,装配一个与之同类型的 Bean
constructor 通过构造方法初始化 Bean 的属性,并依据参数的类型,装配一个与参数同类型的 Bean

尽管自动装配很强大,但是代价是降低了 Bean 配置的可读性。在实践中,建议仅在依赖关系不复杂的应用中使用。

七、注解代替XML配置

component-scan标签默认情况下自动扫描指定路径下的包(含所有子包),将带有@Component、@Repository、@Service、@Controller标签的类自动注册到spring容器。对标记了 Spring's @Required、@Autowired、JSR250's @PostConstruct、@PreDestroy、@Resource、JAX-WS's @WebServiceRef、EJB3's @EJB、JPA's @PersistenceContext、@PersistenceUnit等注解的类进行对应的操作使注解生效(包含了annotation-config标签的作用)。

关键是怎么获得通过扫描方式被spring容器管理的bean

getBean的默认名称是类名(头字母小写),如果想自定义,可以@Service(“aaaaa”)这样来指定。
这种bean默认是“singleton”的,如果想改变,可以使用@Scope(“prototype”)来改变。

在 XML 配置文件中加上 <context:component-scan base-package="Bean所在的包路径"/> 即可开启 Spring 的自动扫描功能,这是使用注解替代XML配置的前提。

1、 @Component 注解

@Component 注解用于标注于 Bean 的类上。凡是被标注了该注解的类(只要在扫描路径下)都会被 Spring 创建。

@Component 注解有唯一的属性 value 属性。它用来为 Bean 命名。同理它的语义化子注解也有

@Component 注解有三个语义化的子注解:

  • @Repository(用于持久层)
  • @Service (用于业务层)
  • @Controller(用于 Web 层)

2、@Value 注解

@Value 注解用于标注于简单类型属性上。凡是被标注了该注解的属性都会被 Spring 注入值(赋值)。

@Value 注解有唯一的属性 value 属性。它用来为简单属性指定值。

3、@Autowired 注解

@Autowired 注解用于标注于引用类型属性上。凡是被标注了该注解的属性都会被 Spring 以 类型 为依据注入另一个 Bean 的引用。

@Autowired 注解有唯一的属性 required 属性(默认值为 true)。它用来指示该对该属性的注入是否为必须(默认必须),即,在 Spring IoC 容器中没有发现符合类型的其他Bean时,会抛出异常。

4、@Qualifier 注解(配合@Autowired注解使用)

@Qualifier 注解需要结合 @Autowired 注解使用。它用于标注于引用类型属性上。凡是被标注了该注解的属性都会被 Spring 以 名字 为依据注入另一个 Bean 的引用。

@Qualifier 注解有唯一的属性 value 属性。它用于指示需要注入的另一个 Bean 的名字。

5、@Resource 注解

它是JDK自带的注解,它是@Autowired && @Qualifier两种注解的结合体

默认先通过Bean的Id、名来寻找并注入,如果找不到就通过类型来注入

八、Bean 的作用域

默认情况下,Spring IoC 容器只会对一个 Bean 创建一个实例。即单例。Spring IoC 提供了 4 种 作用域,它决定了 Spring IoC 是否/何时 生成一个新的对象。常见有:

  • singleton(单例):默认值。在整个应用中,Spring 只为其生成一个 Bean 的实例。
  • prototype(原型):Spring 每次都会生成一个 Bean 的实例。

在 XML 配置文件中, 通过 bean 元素的 scope 属性进行设置。该属性取值:singleton | prototype | 其他 。

在 注解 配置中,使用 @Scope 注解,该注解标注于 Bean 的类上(常见于 @Component 之下)。该注解有唯一属性 value 属性,其取值有: singleton | prototype | 其他。

原文地址:https://www.cnblogs.com/whitespaces/p/12442422.html