六、Bean的装配方式
Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean的装配方式。
6.1 基于XML的装配
Spring提供了两种基于XML的装配方式:设值注入(setter方式注入)和构造注入。
Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求:
- Bean类必须提供一个默认的无参构造方法;
- Bean类必须为需要注入的属性提供对应的setter方法。
实体类User.java
//实体类User
package com.spring.pojo;
import java.util.List;
public class User {
private String username;
private int password;
private List<String> list;
/**
* 1.使用构造注入
* 提供带有所有参数的有参构造方法
* @param username
* @param password
* @param list
*/
public User(String username, int password, List<String> list) {
this.username = username;
this.password = password;
this.list = list;
}
/**
* 2.设值注入
* 2.1 提供默认空参构造函数
* 2.2 为所有属性提供setter方法
*/
public User() {
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(int password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password=" + password +
", list=" + list +
'}';
}
}
配置文件applicationContext.xml
<?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
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--1.使用构造注入方式装配User实例-->
<bean id="user1" class="com.spring.pojo.User">
<constructor-arg index="0" value="tom"/>
<constructor-arg index="1" value="123456"/>
<constructor-arg index="2">
<list>
<value>"constructorvalue1"</value>
<value>"constructorvalue2"</value>
</list>
</constructor-arg>
</bean>
<!--2.使用设置注入方式装配User实例-->
<bean id="user2" class="com.spring.pojo.User">
<property name="username" value="张三"/>
<property name="password" value="654321"/>
<property name="list">
<list>
<value>"setlistvalue1"</value>
<value>"setlistvalue2"</value>
</list>
</property>
</bean>
</beans>
测试类test.java
package com.spring.test;
import com.spring.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test {
public static void main(String[] args) {
//加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/spring/applicationContext.xml");
User user1 = (User) applicationContext.getBean("user1");
User user2 = (User) applicationContext.getBean("user2");
//构造当时输出结果
System.out.println(user1);
System.out.println(user2);
}
}
6.2 基于Annotation(注解)的装配
在Spring中,尽管使用xml配置文件可以实现Bean的装配工作,但如果应用中有很多Bean时,会导致xml配置文件过于臃肿,给后续的维护和升级工作带来一定的困难。因此,Spring提供了对Annotation(注解)技术的全面支持。
Spring中常用的注解:
注解名称 | 注解描述 |
---|---|
@Component | 描述Spring中的Bean,是一个泛华的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次,使用时只需将该注解标注在相应类上即可。 |
@Repository | 用于将数据访问层(Dao层)的类标识为Spring中的Bean,其功能与@Component相同 |
@Service | 通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同 |
@Controller | 通常作用在控制层,用于将控制层的类标识为Spring中的Bean,其功能与@Component相同 |
@Autowired | 用于对Bean的属性变量、属性的setter方法以及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配 |
@Resource | 其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。 |
@Qualifier | 与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier的参数指定 |
小贴士:
- @Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按照Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。
- @Component 注解是一个泛华的概念,与@Repository、@Service和@Controller作用相同;
- @Qualifier一般和@Autowired 联合使用,其联合效果和@Resource使用效果相同。
数据访问层UserDao.java及其实现类UserDaoImpl.java
//UserDao.java
package com.spring.dao;
public interface UserDao {
public void save();
}
//UserDaoImpl.java
package com.spring.dao.impl;
import com.spring.dao.UserDao;
import org.springframework.stereotype.Repository;
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("执行dao层的save方法...");
}
}
业务层UserService.java及其实现类UserServiceImpl.java
//UserService.java
package com.spring.service;
public interface UserService {
public void save();
}
//UserServiceImpl.java
package com.spring.service.impl;
import com.spring.dao.UserDao;
import com.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource(name="userDao")
//@Autowired
UserDao userDao;
@Override
public void save() {
userDao.save();
System.out.println("执行service层的save方法...");
}
}
控制层UserController.java
package com.spring.controller;
import com.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller("userController")
public class UserController {
//@Resource(name="userService")
//@Autowired
UserService userService;
public void save(){
userService.save();
System.out.println("userController的save方法执行...");
}
}
配置文件applicationContext_annotation.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!--开启注解-->
<context:annotation-config/>
<!--分别定义3个Bean的实例-->
<bean id="userDao" class="com.spring.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.spring.service.impl.UserServiceImpl"/>
<bean id="userController" class="com.spring.controller.UserController"/>
<!--配置注解扫描包--通知Spring扫描指定包下所有的Bean类,进行注解解析(推荐使用)-->
<context:component-scan base-package="com.spring.*"/>
</beans>
小贴士:
- 很明显,实例化3个bean的方式很繁琐,不利于代码的维护,所以我们一般采用配置注解扫描包的方式进行配置!!
- 使用@Autowire注解和@Resource注解可以达到同样的效果!!
测试类test.java
package com.spring.test;
import com.spring.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class tset2 {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("src/com/spring/applicationContext_annotation.xml");
UserController userController = (UserController) context.getBean("userController");
userController.save();
}
}
6.3 自动装配
Spring的bean元素中包含一个autowire属性,通过设置autowire的属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动地注入到其他Bean的Property中。
autowire属性有5个值:
属性值 | 说明 |
---|---|
default(默认值) | 由bean的上级标签beans的default-autowire属性值确定 |
byName | 根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean,并将其属性自动装配 |
byType | 根据属性的数据类型(Type)自动装配,如果一个Bean的数据类型兼容另一个Bean中属性的数据类型,则自动装配 |
constructor | 根据构造函数参数的数据类型进行byType模式的自动装配 |
no | 在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义 |
分别在UserServiceImpl.java和UserController.java类中添加类的setter方法:
//UserServiceImpl.java
package com.spring.service.impl;
import com.spring.dao.UserDao;
import com.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
userDao.save();
System.out.println("执行service层的save方法...");
}
}
//UserController.java
package com.spring.controller;
import com.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller("userController")
public class UserController {
UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public void save(){
userService.save();
System.out.println("userController的save方法执行...");
}
}
在配置文件中加入autowire属性:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!--开启注解-->
<context:annotation-config/>
<!--分别定义3个Bean的实例-->
<bean id="userDao" class="com.spring.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.spring.service.impl.UserServiceImpl" autowire="byName"/>
<bean id="userController" class="com.spring.controller.UserController" autowire="byName"/>
</beans>