spring配置bean
使用xml配置
使用构造器创建
构造器创建bean是最常用的,如果不使用构造注入,Spring会调用无参构造器来创建实例
使用的是反射机制,要求该bean所对应的类必须有一个无参构造器
而对于注入方式,有构造器注入和setter方法注入
依赖注入方式
setter方法注入
使用setter方法注入时,注意一定要有无参构造器,spring会根据配置的class来使用class.newInstance()方法来实例化该bean
1 |
|
注意:bean配置的property属性的name值表示的是setter风格的属性,即setter方法去掉set之后首字母小写的名称,并不是和成员变量进行对应
null值设置
1 | <bean id="helloWorld" class="com.zhanghe.study.spring4.beans.helloworld.HelloWorld"> |
注入不同的类型
简单类型使用value
1
<property name="name" value="Spring Hello"/>
引用类型使用ref
1
<property name="car" ref="car2"/>
集合类型list
1
2
3
4
5
6<property name="cars">
<list>
<ref bean="car"/>
<ref bean="car2"/>
</list>
</property>集合类型set
1
2
3
4
5
6<property name="cars">
<set>
<ref bean="car"/>
<ref bean="car2"/>
</set>
</property>集合类型map
1
2
3
4
5
6<property name="carMap">
<map>
<entry key="AA" value-ref="car"/>
<entry key="BB" value-ref="car2"/>
</map>
</property>集合类型 properties
1
2
3
4
5
6<property name="testProp">
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
构造方法注入
1 | <!-- |
获取bean
1 | // 创建spring的IOC容器 |
配置bean引用
如果bean之间有引用关系,可以使用ref来指定引用关系
1 | public class Person { |
这里的ref中写的是其他bean的id值
1 | <bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car"> |
配置集合属性
可以使用<list>
、<set>
、<map>
来对集合属性赋值
1 | <bean id="person" class="com.zhanghe.study.spring4.beans.beantest.Person"> |
还有一种集合bean的方式,可以进行配置集合属性
1 | <!-- 配置集合bean --> |
在需要使用集合的bean中直接引用该集合bean
1 | <bean id="person1" class="com.zhanghe.study.spring4.beans.beantest.Person"> |
使用工厂bean来创建实际bean
对于某些对象的实例化过程特别的繁琐,更希望使用java代码来完成实例化过程,可以提供一个实现FactoryBean接口的工厂bean来生产所实际需要的bean对象
请区分开FactoryBean和BeanFactory,FactoryBean本身来说是一个bean,而BeanFactory确是Bean的工厂
1 | /** |
使用该factoryBean对象时,由于该bean实现了FactoryBean,所以spring不会把它作为一个普通的bean来处理,而是作为一个工厂bean,调用getObject()方法来创建实际需要的bean对象
1 | <bean id="c" class="com.zhanghe.study.spring4.beans.beantest.CarFactoryBean"></bean> |
使用静态工厂方法创建Bean
使用静态工厂方法创建bean实例时,class属性也必须指定,此时的class属性并不是指定Bean实例的实现类,而是静态工厂类,Spring通过该属性知道由哪个工厂类来创建Bean实例,还可以使用factory-method属性来指定静态工厂方法,Spring将调用静态工厂方法返回一个Bean实例,静态工厂方法需要参数的话,使用<constructor-arg>
元素指定
1 | public class StaticCarFactory { |
1 | <!-- 通过静态工厂方法来配置bean |
优点:将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,不需要关心创建对象的细节
调用实例工厂方法创建bean
实例工厂与静态工厂只有一个不同,静态工厂只需要使用工厂类即可,实例工厂需要工厂实例,使用factory-bean指定工厂实例
1 | public class InstanceCarFactory { |
1 | <!-- 配置工厂实例 --> |
自动装配
上述的操作方式全是手动进行注入的,如何进行自动装配呢,可以使用autowire属性来配置
1 | <!-- 自动装配 --> |
如果使用byType,但是存在多个该类型的bean的话,就会出现异常
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.zhanghe.study.spring4.beans.beantest.Car’ available: expected single matching bean but found 2: car,car2
歧义性处理
在自动装配时有时会遇到该接口有多个不同的实现类,此时spring不知道选择哪个来进行注入,就会出现NoUniqueBeanDefinitionException异常
可以使用primary来设置其中一个可选bean为首选项
1 | <bean id="car" class="com.zhanghe.study.spring4.beans.beantest.Car" primary="true"> |
使用注解配置
spring可以在classpath下进行组件扫描,可扫描的注解有
- @Component 基本注解,表示是一个受spring管理的组件
- @Respository 表示持久层组件
- @Service 表示业务层组件
- @Controller 表示表现层组件
spring扫描到组件后,有默认的命名策略,将扫描到的类名进行首字母小写,也可以在注解中使用value属性值来标识组件的名称
如果使用注解来标识bean的话,需要进行配置指定spring扫描的包,会扫描base-package指定的包及其子包
<context:component-scan base-package=”包名”/>
使用注解进行配置
使用注解进行配置时要先开启组件扫描
1 | <!-- 开启组件扫描 设置包扫描路径,如果扫描多个包,使用,隔开 --> |
还可以自定义的设置对于该包下的某些组件是否进行扫描
在使用<context:component-scan base-package=”包名”/>标签时,记得要加上context的命名空间
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
设置过滤
使用context:exclude-filter来设置排除哪些特定的组件
1 | <context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest"> |
设置包含
使用context:include-filter来设置只扫描哪些特定的组件
1 | <context:component-scan base-package="com.zhanghe.study.spring4.beans.annotationtest" use-default-filters="false"> |
自动装配
使用xml进行自动装配的时候略显笨拙,而且使用起来也并不顺心,因为autowire只能选择byName或者byType,如果存在多个相同类型的bean使用byType就会出现问题,大家可能因此想要放弃自动装配,其实自动装配与注解搭配起来还是很好用的,下面来了解一下
如果bean与bean之间存在关联关系,如在beanA中需要调用beanB的方法,如何来获取beanB中的实例呢?
<context:component-scan>元素会自动注册AutowiredAnnotationBeanPostProcessor实例和CommonAnnotationBeanPostProcessor实例,AutowiredAnnotationBeanPostProcessor实例可以自动装配具有@AutoWired注解的属性,CommonAnnotationBeanPostProcessor实例可以自动装配@Resource注解的属性
在基于注解方式实现属性注入时主要使用的四个注解
@Autowired默认使用byType,如果存在类型相同的两个bean,则使用byName来根据属性的名称来匹配bean,默认情况下该依赖对象必须存在,如果允许不存在,需要配置@Autowired(required = false)
@Qualifier 根据属性名称进行注入byName,需要和@Autowired一起使用,使其按照类型的基础上按照name进行注入,给字段注入时不可独立使用,必须要和@Autowired一起使用;但是给方法参数注入时,可以独立使用
@Resource注解可以根据类型注入,也可以根据名称注入,若使用的byName,需要提供bean的名称,如果不提供该bean的名称,则自动使用属性的名称进行匹配
@Inject与@AutoWired一样,只是没有required属性
使用方式
使用@Autowired 和@Qualifier结合来明确指定需要装配的Bean
1
2
3
private BpmService bpmService;使用@Inject和@Named结合来指定
1
2
3
private CompensateService compensateService;
歧义性处理
在自动装配时有时会遇到该接口有多个不同的实现类,此时spring不知道选择哪个来进行注入,就会出现NoUniqueBeanDefinitionException异常,可以使用@Primary来标注其中一个可选bean为首选项,也可以使用@Qualifier注解来选择注入哪个bean的id