Bean的装配方式
Bean的装配方式也即是依赖关系的注入方式,依赖注入可通过setter方法注入、构造方法注入。Spring容器主要支持基于XML的装配、基于Annotation的装配(通过setter方法注入在Annotation中的实现)和自动装配。下面分别介绍
基于XML的装配方式
设值注入(通过setter方法)
基于XML的装配方式可通过setter方法或构造方法注入,当通过setter方式注入时需满足两个条件
- 默认的无参构造方法
- 提供属性的setter方法
如下所示通过setter方式在userDaoImpl中装配username和password属性
package dao;
public class UserDaoImpl implements UserDao {
private String username;
private String password;
public UserDaoImpl() {
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public void save() {
System.out.println("hello,User Dao...My name is "+username+" password is "+password);
}
}
UserDaoImpl的对象作为UserServiceImpl成员变量
package service;
import dao.UserDao;
public class UserServiceImpl implements UserService {
private UserDao userDao;
//添加set方法,用于依赖注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//实现了UserService中的方法
@Override
public void addUser() {
userDao.save();
System.out.println("hello,User Service...");
}
}
bean.xml文件中使用set方式装配普通成员变量与对象成员变量
<!-- 将指定对象配置给spring,让spring创建实例 -->
<bean id="userDao" class="dao.UserDaoImpl">
<!-- 通过设值注入装配Bean -->
<property name="username" value="zhangsan"></property>
<property name="password" value="123456"></property>
</bean> <bean id="userService" class="service.UserServiceImpl">
<!-- 设值注入方式 将userDao实例注入到userService实例中(使用setter方法) 与userDao实例装配Bean方式一样不过这里成员变量是对象 value改为ref -->
<property name="userDao" ref="userDao"></property>
Test方法
@Test public void testUserDao()
{
String xmlPath = "beans.xml"; //初始化spring容器,加载配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); //通过容器获取userDao实例
UserDao userDao = (UserDao)applicationContext.getBean("userDao");
userDao.save(); }
@Test public void testService()
{
String xmlPath="beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath); UserService userService = (UserServiceImpl)applicationContext.getBean("userService"); userService.addUser();
}
测试结果
hello,User Dao...My name is zhangsan password is 123456
hello,User Service...
通过构造方法注入
通过构造方法注入只需实现为属性赋值的构造方法,配置文件中使用<<constructor-arg>仍以上面为例,在UserServiceImpl中通过构造方法引入UserDaoImpl对象配置文件如下:
<!-- 使用构造方法注入 -->
<constructor-arg name="userDao1" ref="userDao"></constructor-arg>
UserDaoImpl中为普通成员变量注入
<!-- 使用构造方法注入 -->
<constructor-arg index="0" value="jack"></constructor-arg> <constructor-arg index="1" value="1234"></constructor-arg>
基于Annotation装配
为了防止有过多的Bean导致配置文件繁琐,可使用注解的功能.web开发,提供3个@Component注解衍生注解(功能一样)
@Repository :dao层 (数据访问层)
@Service:service层 (业务层)
@Controller:Constroller层 (控制层)
这三个注解和@Component一样,在web开发中使用这三个注解是代码更加清晰明了。
除了上面三个类注解,Spring还提供了@Value取代xml中的普通字段值,和使用@Resource取代xml中的字段引用值(实现相同功能的注解还有@Autowired和@Autowired与@Qualifier配合使用)。
上面的例子使用注解方式配置如下:
xml配置 context:component-scan标签
<?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: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
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 使用注解的方式装配Bean -->
<context:component-scan base-package="annotation"/>
</beans>
UserDaoimpl(数据持久dao层)类中使用Reposity注解
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
// TODO Auto-generated method stub
System.out.println("userDao...save...");
}
}
UserServiceImpl(业务逻辑service层)使用Service注解,有引用字段userDao
@Service("userService")
public class UserServiceImpl implements UserService{
@Resource(name="userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
// TODO Auto-generated method stub
userDao.save();
System.out.println("userService...save...");
}
UserAction(业务流程控制Action层),使用Controller注解,有引用字段userService
@Controller("userAction")
public class UserAction {
@Resource(name="userService")
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public void save() {
userService.save();
System.out.println("userAction...save...");
}
测试类代码
@Test
public void testAnnotation() {
//文件配置路径
String xmlPath="annotation/beans2.xml";
//加载配置文件,获得应用上下文实例
ApplicationContext context =
new ClassPathXmlApplicationContext(xmlPath);
UserAction userAction = (UserAction)context.getBean("userAction");
System.out.println(userAction);
userAction.save();
}
输出结果:
八月 21, 2017 1:08:19 上午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@368239c8: startup date [Mon Aug 21 01:08:19 CST 2017]; root of context hierarchy
八月 21, 2017 1:08:19 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [annotation/beans2.xml]
annotation.UserAction@3ffcd140
userDao...save...
userService...save...
userAction...save...
自动装配
需配置bean元素的autowire属性,该属性有五个值:byName,byType,constructor,autodetect,no
可将上例中beans.xml配置文件改成如下(类不需使用注解):
使用自动装配方式,类中不需使用注解,装配引用字段直接通过id自动装配
<bean id="userDao" class="annotation.UserDaoImpl"></bean>
<bean id="userService" class="annotation.UserServiceImpl" autowire="byName"></bean>
<bean id="userAction" class="annotation.UserAction" autowire="byName"></bean>
使用自动装配方式,类中不需使用注解,装配引用字段直接通过id自动装配
<bean id="userDao" class="annotation.UserDaoImpl"></bean>
<bean id="userService" class="annotation.UserServiceImpl" autowire="byName"></bean>
<bean id="userAction" class="annotation.UserAction" autowire="byName"></bean>
输出结果与使用注释一致。