Spring配置概述
在使用Spring提供的各项丰富而神奇的功能前,必须在SpringIOC容器中装配好Bean,并建立Bean和Bean间的关联关系。
Spring容器高层视图
要使得应用程序中的Spring容器成功启动,需要同时具备以下三方面的条件:
- Spring框架的类包都已经放到应用程序的类路径下。
- 应用程序为Spring提供了完备的Bean配置信息。
- Bean的类都已经放到应用程序的类路径下。
Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配好Bean间的依赖关系,为上层应用提供准备就绪的运行环境。
Bean配置信息是Bean的元数据信息,由以下4个方面组成:
- Bean的实现类。
- Bean的属性信息。
- Bean的依赖关系。Spring根据依赖关系配置完成Bean之间的装配。
- Bean的行为配置。如生命周期范围以及生命周期各过程的回调函数等。
Spring元数据信息在Spring容器中的内部对应物是由一个个的BeanDefinition形成的Bean注册表,Spring实现了Bean元数据信息内部表示和外部定义的解耦。Spring支持多种形式的Bean定义:
- XML配置。
- 注解配置。
- Java类配置。
- Groovy动态语言配置。
Bean基本配置
一个简单的Bean的配置如这样:<bean id = "Foo" class ="com.smart.Foo"/>
一般情况下一个Bean对应配置文件当中一个<bean>,通过容器的getBean("foo")
即可获得对应的bean,而class指定了实现类。
Bean的命名
一般情况下id在IOC容器中必须是唯一的,但是可以定义多个不同的name,如果不指定id与name之一,则会将全限定名作为Bean的名称。
DI
- 属性注入、构造函数注入、工厂注入。
注入方式
属性注入
属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring首先调用Bean默认的构造函数实例化Bean,然后通过反射的方式调用Setter方法注入属性值。
例如:
1 | <bean id ="" class =""> |
构造函数注入
保证一些必要的属性在Bean实例化时就得到设置,确保Bean在实例化后就可以使用。
工厂方法注入
是DI和单实例设计思想的主要实现方法。
1 | <bean id = "carFactory" class = ""> |
注入参数详解
引用其他Bean
bean可以通过<ref>元素引用其他Bean,建立起对其他bean的依赖。
当实例化时,Spring保证该Bean依赖的其他Bean已经初始化。
1 | <bean id = "boss" class = ""> |
ref可以通过以下三个属性引用容器中的其他Bean:
- bean:通过该属性可以引用同意容器或父容器中的Bean,是最常见的方式。
- local:只能引用同一配置文件中定义的bean。
- parent:引用父容器中的Bean。
内部Bean
内部Bean不能被其他Bean引用。
1 | <bean id = "boss" class = ""> |
方法注入
bean间的关系
<bean>元素标签间也可以建立类似于ref间的依赖关系。
继承
如果多个类拥有相同的方法和属性,则可以引入一个父类,在父类中定义这些类的共同的方法和属性,以消除重复的代码。即多个bean当中存在同样的配置信息,允许定义一个父bean。
1 | <bean id = "" class = "" parent = ""> |
依赖
在某些情况下,Bean间依赖关系并没有那么明显,因此使用ref并不合适。
某些情况下Bean A希望在Bean B加载并完成系统参数设置后再启动,则必须保证Bean B在Bean A前初始化。可以depends-on属性显式指定Bean前置依赖的Bean。
1 | <bean id = "manag" class = "" depends-on = "otherBean"> |
引用
如果一个bean要引用另一个bean的id值则可以如下配置:
1 | <bean id = "car" p:userId = "user" scope = "prototype"> |
如此设置没有建立依赖关系。
整合多个配置文件
基于注解的配置
如@Component
等价于<bean id = “userDao” class = “ “>
@Component
@Service
@Controller
自动装配Autowired
@Autowired实现Bean的依赖注入,其默认按类型匹配的方式在容器中查找匹配的Bean,当有且仅有一个匹配的Bean,则将其注入@Autowired标注的变量。
required
属性,如果当Autowired找不到相应的Bean,则会抛出NoSuchBeanDefinitionException,如果希望不要抛出异常,则设置@Autowired(required = false)
@Qualifier指定注入Bean的名称。
@Autowired可以标注类的方法入参:
1 | //注入LogDao |
也可以标注集合类:
1 | //注入所有类型为Plugin的类。 |
也可以延迟加载,即配置注解@Lazy。
作用范围Scope
@Scope(“prototype”)标注在类上。
Bean作用域
作用域对Bean的生命周期和创建方式产生影响。
- singleton。
- 单例作用域,Spring环境下使用AOP和LocalThread对非线程安全的变量进行了特殊处理,使得这些非线程安全的类变成了线程安全的类,因此在实际应用中,大部分Bean都能以单实例的方式运行。
- prototype。非单例作用域的Bean。
<bean id = "boss" class = "Boss" scope = "prototype">
如此引用下每次通过getBean("boss")
获得的都是一个全新的实例。- Spring启动时不初始化,并在初始化后不再管理其生命周期。
与Web相关,使用WebApplication时可用,并需要一些额外的配置:
- request。对应一个Http请求和生命周期,每次调用完成后即销毁。
- session。作用域跨越整个HTTP session,所有HTTP共享。
- globalSession。