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 容器主要是基于 BeanFactory 和 ApplicationContext 两个接口:
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-ref 和 value-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 容器提供自动装配功能,只需要在 bean 的 autowire 属性中指定自动装配模式就可以了。
装配模式 | 说明 |
---|---|
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
| 其他。