IOC
IoC也称为依赖注入DI,将对象的创建、初始化、销毁等操作交给Spring容器管理
容器
org.springframework.beans
和org.springframework.context
包是 Spring Framework 的 IoC 容器的基础BeanFactory
提供配置框架和基本功能,ApplicationContext
包括BeanFactory
的所有功能,提供更多功能
ApplicationContext和BeanFactory的功能
特征 | BeanFactory |
ApplicationContext |
---|---|---|
Bean实例化/装配 | 是的 | 是的 |
集成的生命周期管理 | 不 | 是的 |
自动BeanPostProcessor 注册 |
不 | 是的 |
自动BeanFactoryPostProcessor 注册 |
不 | 是的 |
方便MessageSource 的访问(国际化) |
不 | 是的 |
内置ApplicationEvent 发布机制 |
不 | 是的 |
ApplicationContext
几种实现类
-
ClassPathXmlApplicationContext
:从classpath下寻找xml配置文件并实例化ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
-
FileSystemXmlApplicationContext
:从文件系统下寻找xml配置文件并实例化ApplicationContext context = new FileSystemXmlApplicationContext("C://beans.xml");
-
AnnotationConfigApplicationContext
:使用Java配置类实例化ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
获取Bean的基本方式
getBean(String name)
:根据对象名获取,需要强制类型转换<T> T getBean(Class<T> requiredType)
:根据类的类型获取,如果存在多个实例会报错<T> T getBean(String name, Class<T> requiredType)
:根据对象名以及类的类型获取
Xml配置
基本结构
id
是用于标识一个Bean的字符串class
是Bean的所属类的全限定类名
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
Bean
容器管理一个或多个bean,bean都是由配置元数据生成的
Bean的命名
- 使用
id
命名只能指定一个名称 - 使用
name
命名可以指定多个名称使用逗号分隔 - 如果不显式提供名称,则容器会自动为该bean生成一个唯一的名称,驼峰命名
在Bean定义之外使用别名
通常在name中为bean提供多个名称,但有时需要在别的地方提供别名,可以使用alias
标签
<alias name="fromName" alias="toName"/>
上面代码为名称为fromName
的bean定义了一个新的别名toName
Bean的实例化
使用构造方法实例化
使用id
或name
指定名称,使用class
指定bean的类
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
如果参数的类型都不一致,则在<constructor-arg>
中指定直接指定参数,无需指定参数的index或类型
<beans>
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg ref="beanTwo"/>
<constructor-arg ref="beanThree"/>
</bean>
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
</beans>
指定构造方法参数的索引
使用index
属性指定参数的位置
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
指定构造方法参数的类型
使用type
属性指定参数的类型
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
指定构造方法参数的名称
使用name
属性指定参数的名称,此功能要在debug flag为启用的状态下才能生效,也可以使用@ConstructorProperties
注解显式命名参数
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
使用静态工厂方法实例化
调用类的静态方法创建bean,使用class
属性指定包含静态工厂方法的类,使用factory-method
指定工厂方法的名称
<bean id="clientService" class="examples.ClientService" factory-method="createInstance"/>
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
使用实例工厂实例化
调用现有bean的实例方法创建新的bean,使用factory-bean
属性指定bean的名称,使用factory-method
指定工厂方法的名称
<bean id="serviceLocator" class="examples.DefaultServiceLocator"></bean>
<bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
}
依赖注入
构造方法注入
根据参数类型自动匹配
如果参数的类型都不一致,则在<constructor-arg>
中指定直接指定参数,无需指定参数的index或类型
<beans>
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg ref="beanTwo"/>
<constructor-arg ref="beanThree"/>
</bean>
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
</beans>
指定构造方法参数的索引
使用index
属性指定参数的位置
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
指定构造方法参数的类型
使用type
属性指定参数的类型
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
指定构造方法参数的名称
使用name
属性指定参数的名称,此功能要在debug flag为启用的状态下才能生效,也可以使用@ConstructorProperties
注解显式命名参数
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>
Setter注入
是通过无参构造器或无参数的工厂方法实例化bean后,调用bean的setter方法注入bean
<bean id="exampleBean" class="examples.ExampleBean">
<property name="years" value=7500000></property>
<property name="ultimateAnswer" value="42"></property>
</bean>
使用构造函数注入还是Setter注入
- 可以混合使用两种方法,通常将必须的依赖项使用构造函数注入,可选的依赖项使用setter注入
- 可以使用
@Required
注解标注在对应的setter方法上,确保该依赖项是必须的,否则会报错 - 构造方法注入通常可以确保所需的依赖不是null
- 特定的类可以使用适合的方法,如果一个第三方类没有提供setter方法,那么只能使用构造函数
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/244735.html