Spring基础——在Spring Config 文件中配置 Bean
本文内容纲要:Spring基础——在Spring Config 文件中配置 Bean
一、基于 XML 的 Bean 的配置——通过全类名(反射)
<bean
id="hello"
class="com.atguigu.spring.helloworld.HelloWorld">
1.通过属性注入
即通过 setXxx() 方法注入 Bean 的属性值或依赖的对象。
使用
也可以通过
e:
<bean id="helloWorld" class="com.nucsoft.spring.helloworld.HelloWorld"> <property name="hello" value="spring"/>
<property name="world">
<value>spring</value>
</property>
</bean>
注意:在此种方式下,要配置的 Bean 必须存在空参构造器。
2.通过构造器注入
通过构造方法注入属性值或依赖的对象。
使用
通过 name 属性、index 属性、type属性提供了三种注入方式:
(1)name:按照构造器参数名匹配入参
<bean id="car1" class="com.nucsoft.spring.helloworld.Car"> <constructor-arg name="brand" value="奥迪"/>
<constructor-arg name="corp" value="上海"/>
<constructor-arg name="price" value="400000"/>
</bean>
(2)index:按照索引匹配入参
<bean id="car2" class="com.nucsoft.spring.helloworld.Car"> <constructor-arg index="0" value="大众"/>
<constructor-arg index="1" value="10000"/>
</bean>
(3)type:按照类型匹配入参
<bean id="car3" class="com.nucsoft.spring.helloworld.Car"> <constructor-arg type="java.lang.String" value="宝马"/>
<constructor-arg type="double" value="200000"/>
</bean>
注意:Spring 虽然提供了通过构造器的方式进行注入,但是并不推荐使用此种方式。
3.细节问题
(1)若注入的属性值包含特殊字符,可以使用 <![CDATA[]]> 包含该属性值。
如:
<bean id="car4" class="com.nucsoft.spring.Car"> <property name="brand">
<value><![CDATA[<BM>]]> </value>
</property>
<property name="corp" value="德国"/>
<property name="maxSpeed" value="230"/>
<property name="price" value="20000000"/>
</bean>
(2)可以通过 元素或 ref 属性为 Bean 的属性或构造器指定对 Bean 的引用。
如:
e1:
<bean id="service" class="com.nucsoft.spring.Service"/><bean id="action" class="com.nucsoft.spring.Action">
<property name="service" ref="service"/>
</bean>
e2:
<bean id="feather" class="com.nucsoft.spring.Feather"> <property name="length" value="13"/>
</bean>
<bean id="bird" class="com.nucsoft.spring.Bird">
<constructor-arg name="birdName" value="smallBird"/>
<constructor-arg name="feather" ref="feather"/>
</bean>
(3)内部Bean:可以在属性或构造器里包含 Bean 的声明,内部 Bean 不需要指定 id,同时在别的地方也无法引用。
如:
e1:
<bean id="action" class="com.nucsoft.spring.Action"> <property name="service">
<bean class="com.nucsoft.spring.Service"/>
</property>
</bean>
e2:
<bean id="bird" class="com.nucsoft.spring.Bird"> <constructor-arg name="birdName" value="smallBird"/>
<constructor-arg name="feather">
<bean class="com.nucsoft.spring.Feather">
<property name="length" value="13"/>
</bean>
</constructor-arg>
</bean>
4.为引用类型(字符串或对象)注入 Null 值
<bean id="bird" class="com.nucsoft.spring.Bird"> <constructor-arg name="birdName" value="smallBird"/>
<constructor-arg name="feather">
<null/>
</constructor-arg>
</bean>
5.为级联属性注入
(1)通过属性
<bean id="feather" class="com.nucsoft.spring.Feather"> <property name="length" value="44"/>
</bean>
<bean id="bird" class="com.nucsoft.spring.Bird">
<property name="birdName" value="smallBird"/>
<property name="feather" ref="feather"/>
<property name="feather.length" value="23"/>
</bean>
(2)通过构造器
<bean id="feather" class="com.nucsoft.spring.Feather"> <property name="length" value="44"/>
</bean>
<bean id="bird2" class="com.nucsoft.spring.Bird">
<constructor-arg name="birdName" value="bigBird"/>
<constructor-arg name="feather" ref="feather"/>
<property name="feather.length" value="33"/>
</bean>
注意:设置级联属性的前提是,级联属性所属对象已经被注入到容器中。同时需要为级联属性所属对象提供 getXxx() 方法。
6.集合属性
(1)集合性质的类型:List,Set,Map 和 数组
(2)使用 ,
(3)List:通过引用外部 Bean 或 创建内部 Bean 的方式
<bean id="department" class="com.nucsoft.spring.Department"> <property name="deptName" value="dept01"/>
</bean>
<bean id="company" class="com.nucsoft.spring.Company">
<property name="companyName" value="ICBC"/>
<property name="departments">
<list>
<ref bean="department"/>
<bean class="com.nucsoft.spring.Department">
<property name="deptName" value="dept02"/>
</bean>
</list>
</property>
</bean>
测试:
private ApplicationContext ctx = null;@Before
public void init() {
ctx = new ClassPathXmlApplicationContext("spring/ApplicationContext.xml");
}
@Test
public void test01() {
Company com = ctx.getBean(Company.class);
System.out.println(com);
}
输出:
Company{companyName='ICBC', departments=[Department{deptName='dept01'}, Department{deptName='dept02'}]}
(4)Set:与 List 类似。不做重复说明。
(5)Map: 在
如:
<bean id="emp02" class="com.nucsoft.spring.Employee"> <property name="employeeName" value="emp02"/>
<property name="age" value="23"/>
</bean>
<bean id="department" class="com.nucsoft.spring.Department">
<property name="deptName" value="dept01"/>
</bean>
<bean id="department02" class="com.nucsoft.spring.Department">
<property name="deptName" value="dept02"/>
</bean>
<bean id="company" class="com.nucsoft.spring.Company">
<property name="companyName" value="ICBC"/>
<property name="departments">
<map>
<entry key-ref="department" value-ref="emp01"/>
<entry key-ref="department02" value-ref="emp02"/>
</map>
</property>
<property name="strs">
<map>
<entry key="key01" value="value01"/>
<entry key="key02" value="value02"/>
</map>
</property>
</bean>
测试:
private ApplicationContext ctx = null;@Before
public void init() {
ctx = new ClassPathXmlApplicationContext("spring/ApplicationContext.xml");
}
@Test
public void test01() {
Company com = ctx.getBean(Company.class);
System.out.println(com);
}
输出:
Company{companyName='ICBC', departments={Department{deptName='dept01'}=Employee{employeeName='emp01', age=12}, Department{deptName='dept02'}=Employee{employeeName='emp02', age=23}}}
注意:不能在
(6)Properties 类型的属性:和 Map 类似,在
<bean id="DataSourceId" class="com.nucsoft.spring.DataSourceBean"> <property name="propertiesInfo">
<props>
<prop key="user">root</prop>
<prop key="password"></prop>
<prop key="jdbcUrl">jdbc:mysql:///test</prop>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
7.定义单独的集合 Bean
使用基本的集合标签定义集合时,不能将集合作为独立的 Bean 定义,导致其他 Bean 无法引用该集合,所以无法在不同的 Bean 之间共用。
可以使用 util schema 里的集合标签定义独立的集合 Bean。需要注意的是,定义的集合 Bean 与
<bean id="company" class="com.nucsoft.spring.Company"> <property name="companyName" value="ICBC"/>
<property name="departments" ref="departments"/>
</bean>
<util:list id="departments">
<bean class="com.nucsoft.spring.Department">
<property name="deptName" value="dept01"/>
</bean>
<ref bean="department02"/>
</util:list>
可以定义到外部的集合 Bean 有:
8.使用 p 命名空间,简化 XML 配置文件
<bean id="bird3" class="com.nucsoft.spring.Bird" p:birdName="smallBird" p:feather-ref="feather"/>
二、基于 XML 的 Bean 的配置——通过工厂方法
1.通过静态工厂方法
直接调用某一个类的静态方法,可以返回一个 Bean 的实例。通过 class 属性来指定全类名,使用 factory-method 来指定生成 bean 的静态方法。使用 constructor-arg 为静态方法传入参数。如:
<bean class="java.text.DateFormat" id="dateFormat" factory-method="getDateInstance"> <constructor-arg value="1"/>
</bean>
@Test
public void test04() {
DateFormat dateFormat = (DateFormat) ctx.getBean("dateFormat");
System.out.println(dateFormat);
}
适用情况:官方或第三方提供的通过静态方法生成 bean 对象,不需要我们再创建,对应的 Bean 类一般是通过 newInstance 软编码的方式来创建。
2.通过实例工厂方法:将对象创建的过程封装到另外一个对象的方法里。
(1)首先要创建和配置一个含有工厂方法的 Bean
(2)在另一个 bean 配置中调用含有工厂方法 bean 的非 static 方法(即工厂方法)来返回一个 bean 的实例,factory-bean:指向已经创建好的工厂 bean ,factory-method:实例化工厂方法,construtor-arg:为实例工厂方法传入参数。
如:
工厂 Bean 的配置:
<bean class="java.text.SimpleDateFormat" id="simpleDateFormat"> <constructor-arg value="yyyy-MM-dd"/>
</bean>
目标 Bean 的配置:
<bean factory-bean="simpleDateFormat" factory-method="parse" id="date"> <constructor-arg value="2012-02-24"/>
</bean>
测试:
@Testpublic void test05() {
Date date = (Date) ctx.getBean("date");
System.out.println(date);
}
控制台输出:
Fri Feb 24 00:00:00 CST 2012
三、基于 XML 的 Bean 的配置——通过 FactoryBean 配置 Bean
1.Spring 中有两类 Bean,一种是普通 Bean,另外一种是工厂 Bean,即 FactoryBean
2.工厂 Bean 与普通 Bean 不同,其返回的对象不是指定类的一个实例,其返回的是该工厂 Bean 的 getObject() 方法返回的对象
3.具体操作
(1)目标工厂 Bean 需要实现 FactoryBean 接口
(2)返回的对象为 getObject() 方法返回的对象。
如:
工厂 Bean:
/** * @author solverpeng
* @create 2016-07-19-11:45
*/
public class DepartmentFactoryBean implements FactoryBean<Department>{
@Override
public Department getObject() throws Exception {
Department department = new Department();
department.setDeptName("dept01");
department.setEmployee(new Employee());
return department;
}
@Override
public Class<?> getObjectType() {
return Department.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
Spring Config 配置:
<bean class="com.nucsoft.spring.bean.DepartmentFactoryBean" id="department"/>
测试:
@Testpublic void test06() {
Department department = (Department) ctx.getBean("department");
System.out.println(department);
}
三、基于注解的 Bean 的配置
前提:需要导入 spring-aop-4.0.0.RELEASE.jar 包
1.在 classpath 中扫描组件(component scanning):Spring 能够从 classpath 下自动扫描和实例化具有特定注解的组件。
2.特定的组件包括:
(1)@Component:基本注解,标识了一个受 Spring 管理的组件
(2)@Respository:标识持久层组件
(3)@Service:标识服务层组件
(4)@Controller :标识表现层组件
3.对于扫描到的组件,Spring 有默认的命名策略:使用简短类名,第一个字母小写。也可以通过 value 属性指定名称。
4.当在组件类上使用了特定注解后,还需要在 Spring 的配置文件中声明 context:component-scan。
属性:
**base-package:**指定要扫描的基类包,Spring会自动扫描这个基类包及其子包中的所有类。当需要扫描多个包是,可以使用逗号进行分割。
如:
<context:component-scan base-package="com.nucsoft.spring"/>
**resource-pattern:**若需要扫描基包下指定的类,可以使用该属性过滤特定的类。默认是:"**/*.class"。
如:
<context:component-scan base-package="com.nucsoft.spring" resource-pattern="component/*.class" />
<context:include-filter type="" expression=""/> 子节点表示要包含的目标类
<context:exclude-filter type="" expression=""/> 子节点表示要排出在外的目标类
可以同时包含多个 <context:include-filter type="" expression=""/> 和 <context:exclude-filter type="" expression=""/> 子节点
属性 type:表示支持不同类型的过滤
annotation:所有标注某注解的类。该类型采用目标类是否标注了某注解进行过滤
e:所有在基包下标注 @Controller 注解的类都不被扫描
<context:component-scan base-package="com.nucsoft.spring"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
**assinable:**所有继承或扩展某个特定的类进行过滤
e:所有继承或扩展 Person 类的类都不被扫描
<context:component-scan base-package="com.nucsoft.spring" resource-pattern="component/*.class"> <context:exclude-filter type="assignable" expression="com.nucsoft.spring.bean.Person"/>
</context:component-scan>
四、基于注解来装配 Bean 的属性
1.context:component-scan 还会自动注册 AutowiredAnnotationBeanPostProcessor 实例,该实例可以自动装配具有 @Autowired 和 @Resource、@Inject 注解的属性。
2.@Autowired 注解
自动装配目标 Bean 的 Bean 属性(该属性为一个 Bean 的实例,该 Bean 为在 IOC 容器中存在的 Bean)
(1)可以对属性标注该注解。如:
/** * @author solverpeng
* @create 2016-07-19-16:49
*/
@Component
public class Department {
private String deptName;
@Autowired
private Employee employee;
@Autowired
private Address address;
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", employee=" + employee +
", address=" + address +
'}';
}
}
(2)可以对方法标注该注解,方法参数为要自动装配的类型,可以是任意方法
/** * @author solverpeng
* @create 2016-07-19-16:49
*/
@Component
public class Department {
private String deptName;
private Employee employee;
private Address address;
@Autowired
public void setAddress(Address address) {
this.address = address;
}
@Autowired
public void abc(Employee employee) {
this.employee = employee;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", employee=" + employee +
", address=" + address +
'}';
}
}
(3)可以对构造器标注该注解,方法参数为要自动装配的类型。
/** * @author solverpeng
* @create 2016-07-19-16:49
*/
@Component
public class Department {
private String deptName;
private Employee employee;
private Address address;
public void setDeptName(String deptName) {
this.deptName = deptName;
}
@Autowired
public Department(Employee employee, Address address) {
this.employee = employee;
this.address = address;
}
@Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", employee=" + employee +
", address=" + address +
'}';
}
}
注意:
使用 @Autowired 自动匹配时,如果只匹配到一个的情况下:
按照类型进行匹配
如果匹配到多个:
标记有 primary="true" 的 bean 有限,不能同时出现多个 primary="true" 的相同类型的 bean。否则:UnsatisfiedDependencyException
若都没有 primary 属性,在按照 @Autowired 标注的构造器或方法 的参数名称进行匹配 Bean。若还没有匹配到,则报:UnsatisfiedDependencyException异常。
具体参见:
org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates
org.springframework.beans.factory.support.DefaultListableBeanFactory#determinePrimaryCandidate
(4)若某一个属性允许不被设置,可以设置 @Autowired 注解的 required 属性为 false。
(5)@Qualifier 注解:Spring 允许对方法的入参或属性标注 @Qualifier 注解。@Qualifier 注解里提供 Bean 的名称。
如:
属性处:
@Autowired@Qualifier("address2")
private Address address;
方法处:
@Autowiredpublic Department(Employee employee, @Qualifier("address2") Address address) {
this.address = address;
this.employee = employee;
}
(6)@Autowired 注解可以标识在数组类型的属性上,此时会把所有匹配的 Bean 进行自动装配
(7)@Autowired 注解可以标识在集合属性上,此时会将集合类型对应的 Bean 进行自动装配
(8)@Autowired 注解可以标识在 Map 上,若 key 为 String,则此时会将 value 对应的 Bean 的类型进行自动装配
3.@Resource 注解
(1)如果说 @Autowired 属性是按照类型进行自动装配的,那么 @Resource 注解可以看成是按照名称进行装配的。
@Resource 注解要求提供一个 Bean 名称的属性,若该属性为空,则自动采用标注出的变量或方法名作为 Bean 的名称。
注意:不能标注于构造器。
4.@Inject 注解
和 @Autowire的 注解一样也是按照类型匹配注入的 Bean ,但是没有 required 属性。
5.最后,对比一下@Resource和@Autowired
(1)@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入
(2)@Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用
(3)@Resource注解是又J2EE提供,而@Autowired是由spring提供,故若要减少系统对spring的依赖建议使用 @Resource的方式;
6.最最后,推荐使用 @Autowired 注解。
本文内容总结:Spring基础——在Spring Config 文件中配置 Bean
原文链接:https://www.cnblogs.com/solverpeng/p/5673415.html
以上是 Spring基础——在Spring Config 文件中配置 Bean 的全部内容, 来源链接: utcz.com/z/296069.html