Spring容器
在Spring中,bean是生存于Spring容器中。Spring自带了很多的容器,大致归为两种不同的类型:
1、bean工厂(org.springframework.beans.factory.beanFactory接口定义)
2、应用上下文(org.springframework.context.ApplicationContext接口定义)。
bean工厂是最简单的容器,提供简单的DI支持。应用上下文是基于BeanFactory构建,提供应用框架级别的服务。
Spring中带有多种类型的应用上下文。最可能遇见下面几个类型。
- AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载Spring应用上下文。
- AnnotationConfigWebApplicationContext:从一个或多个基于java的配置类中加载Spring Web应用上下文。
- ClassPathXmlApplicationContext:从类路径下的一个或多个XML配置文件中加载上下文定义,把应用上下文的定义文件作为类资源。
- FileSystemXmlapplicationcontext:从文件系统下的一个或者多个XML配置文件中加载上下文定义。
- XmlWebApplicaitonContext:从Web应用下的一个或者多个XML配置文件中加载上下文定义。
Bean的配置
在Spring中有三种主要的装配机制:
1.在XML中显式配置。
2.在java中进行显式配置。
3.隐式的bean发现机制和自动装配。
三种方式各有特点,可以自由选择装配机制,三种风格可以自由搭配。建议尽量使用自动配置的机制,显示配置越少越好。
当某些情况,有部分源代码不是你来维护,但是你需要为其配置bean,则可以使用javaConfig进行显示配置。只有当你想使用便利的XML命名空间的时候,并且javaConfig没有实现,再使用XML来进行配置。
在xml中显示配置
在XML中配置bean,首先要以元素为根。生命一个简单的bean:
构造器注入初始化bean
Spring3.0之后有两种方法来构造bean。
<1> constructor-arg
<2> 使用c-命名空间
两者最大的区别就是是否冗长。
1、将bean注入到构造器
< bean id = "A" class = "B">
< constructor-arg ref="C" />
< / bean>
或者用c-命名空间来进< bean id = “A” class = “B”>
< c:D-ref=“F” />
< / bean>,A是创建bean的ID,B是类的全称,c: 命名空间,D是构造器参数名字,-ref是注入bean的引用,F 要注入bean的ID。
2、将字面量注入到构造器中
< bean id = “A” class = “B”>
< constructor-arg value=“String” />
< / bean>
或者用c-命名空间
(1)
< bean id = “A” class = “B”>
< c:_构造器参数 =“String” />
< / bean>
(2)
< bean id = “A” class = “B”>
< c:_0 =“String” />
< c:_1 =“String” />
< / bean>
3、将集合装配到构造器中
< bean id = "A" class = "B">
< constructor-arg>
< list>
< value>1</value>
< value>2</value>
< value>3</value>
< value>4</value>
< /list>
< /constructor-arg>
< constructor-arg>
< list>
< ref bean= "A" />
< ref bean= "B" />
< ref bean= "C" />
< /list>
< /constructor-arg>
< / bean>
Spring要创建<list> <set>
等元素时,生成的是java.util.Set和java.util.List。set中重复的值会被忽略掉。c-命名空间不能用来装配集合。
bean设置属性
< bean id = "AA" class = "BB">
< property name = "A" ref = "B" />
< property name = "C" value="D" />
< property name = "E">
< list>
< value>1</value>
< value>2</value>
< value>3</value>
< value>4</value>
< /list>
< / property>
< / bean>
A和C是属性名字,B是注入bean的ID,D是字面量,为C赋值。
p-命名空间设置属性
< bean id = “A” class =“B” p:C-ref = “D” />
c是属性名字,D是注入的bean的ID
在java中显示配置
创建配置类 @Configuration 表明这是一个配置类
@ComponentScan 扫描组件
声明一个简单的bean
@Bean
public TemClass getTemClass(){
return new TemClass();
}
自动化装配Bean
Spring从两个角度来实现自动化装配;
1、组件扫描:Spring会自动发现应用上下文中所创建的bean。
2、自动装配:Spring自动满足bean之间的依赖。
###在xml中
组件的扫描两种方式:
1、在XML中启动组件扫描。
<context:component-scan base-pacekage="你要扫描包的全称" />
2、@ComponentScan注解进行组件扫描
当你利用java代码进行组件扫描时候,只需要在你的@Configuration配置类中增加注解@ComponentScan便可自动进行组件扫描。一般不带参数的时候,扫描的是与配置类相同的包以及这个包下的所有子包,查找带有@Component注解的类。
可以设置扫描的基础包,比如@ComponentScan("你要扫描的包"),或者你想清晰的表达你所设置的包,可以通过配置 basePackages属性进行设置@ComponentScan(basePackages="你要扫面的基础包")。
配置basePackages也可以进行扫描多个包@ComponentScan(basePackages={"A","B","C"}),只需要将你所需要扫描的包设置为一个数组即可。
当然,还有另外一种扫描方法,将basePackages换成basePackageClasses。比如@ComponentScan(basePackages={"A.class","B.class","C.class"}),此时将会以这些类所在包为基础包进行扫描。
添加注解自动装配:
@Autowired 自动装配,不仅能用在构造器上,也可以用在setter方法上。@Inject和@Autowired注解大多数情况可以互相替换。
自动装配时可能会出现两种异常:
1、没有找到可以注入的bean。此时你可以设置required属性,@Autowired(required=false).此时如果后面的没有进行null检查的话,可能会抛出NullPointerException异常。
2、可能会查找多个可以匹配的bean。可以标示首选的bean。可以在你想优先注入的bean加入注解@Primary。但是这样又会出现如果多个bean被标识为@Primary,可以使用限定符进行限制条件,在想要注入某个bean的类上增加注解@Qualifier("Bean的ID")进行限定。如果一个bean没有指定其他的限定符,则所有的bean都会给定一个默认的限定符,这个限定符与bean的ID相同。
还可以创建自己的限定符进行限定。
@Targer({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.Method,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold{}
导入和混合配置
java不同的配置类之间通过@Import(A.class)来将两个配置类组合在一起。@ImportResource("/classpath:A.xml")导入xml中配置。
xml通过导入其他xml文件。
通过A是你需要的配置类。
通常用第三个文件去讲所有的文件配置在一起。