基于XML的装配
Spring 提供了两种基于XML的装配方式:设值注入(Setter Injection)和构造入住(Constructor Injection)。
在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此设值注入要求一个Bean必须满足一下两点要求:
- Bean类必须提供一个默认的无参构造方法
- Bean类必须为需要注入的属性提供对应的setter方法。
使用设值注入时,在Spring配置文件中,需要使用
1.新建一个项目导入需要的框架包并在src下建立一个com.cn.assemble包,在包中创建User类,并在类中定义username、password 和 list 集合三个属性以及对应的setter方法,代码如下
package com.cn.assemble;
import java.util.List;
public class User {
private String username;
private Integer password;
private List<String> list;
/*
* 1.使用构造注入
* 2.提供带所有参数的有参构造方法
*/
public User(String username, Integer password, List<String> list) {
super();
this.username = username;
this.password = password;
this.list = list;
}
/*
* 1.使用设值注入
* 2.提供默认空参构造方法
* 3.为所有属性设置setter方法
*/
public User() {
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(Integer password) {
this.password = password;
}
public void setList(List<String> list) {
this.list = list;
}
//重写toString()方法方便观察结果
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + ", list=" + list + "]";
}
}
2.在src下创建beans.xml,在配置文件中通过构造注入和设值注入的方式装配User类的实例,代码如下:
<?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.xsd">
<!-- 使用构造注入方式装配 -->
<bean id="user1" class="com.cn.assemble.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>
<!-- 使用设值注入方式装配 -->
<bean id="user2" class="com.cn.assemble.User">
<property name="username" value="张三"></property>
<property name="password" value="654321"></property>
<!-- 注入list集合 -->
<property name="list">
<list>
<value>"setlistvalue1"</value>
<value>"setlistvalue2"</value>
</list>
</property>
<!--如果是map类型就这样注入-->
<!--
<property name="authorsInfo">
<map>
<entry key="1" value="Deepak" />
<entry key="2" value="Arun"/>
<entry key="3" value="Vijay" />
</map>
</property>
-->
</bean>
</beans>
在上述配置文件中,<constructor-arg>元素用于定义构造方法的参数,其属性index表示索引(从0开始),value 属性用于设置注入的值,其子元素<list>来为
User类中对应的list集合属性注入值。然后又使用了设值注入方式装配User类的实例,其中<property>元素用于调用Bean实例中的setter方法完成属性赋值,从而完成依赖注入,而其子元素同样是为User类中对应的list集合属于注入值。
3.创建测试类XmlBeanAssembleTest,在类中分别获取并输出配置文件中的user1和user2实例。代码如下:
package com.cn.assemble;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class XmlBeanAssembleTest {
@Test
public void Test() {
ApplicationContext appc = new ClassPathXmlApplicationContext("beans.xml");
System.out.println(appc.getBean("user1"));
System.out.println(appc.getBean("user2"));
}
}
运行结果如下所示:
基于Annotation的装配(注解方式,重点!)
Spring 中定义了一系列的注解,常用的注解方式如下:
- @Component:可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应的类上即可。
- @Repository:通常作用在业务层(DAO 层)的类标识为Spring中的Bean,其功能与@Component相同
- @Service:通常作用在业务层(Service 层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同。
- Controller:通常作用在控制层(如Spring MVC 的 Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。
-----------
- @Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。
- @Resource:其作用与@Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name 和 type。Spring将name属性解析为Bean实例名称,type属性解析为Bean的实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果无法匹配,则抛出NoSuchBeanDefinitionException异常。
- Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称有@Qualifier注解的参数指定
下面几步简单的例子演示注解的使用:
1.创建一个com.cn.annotation包,在包中创建接口UserDao,并在接口中定义一个save()方法,代码如下:
package com.cn.annotation;
public interface UserDao {
public void save();
}
2.创建UserDao接口的实现类UserDaoImpl,并实现save()方法,代码如下:
package com.cn.annotation;
import org.springframework.stereotype.Repository;
@Repository("userDao")
public class UserDaoImpl implements UserDao{
public void save() {
System.out.println("userdao...save...");
}
}
首先使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中<bean id="userDao" class="com.cn.annotation.UserDaoImpl"/>的编写。
3.创建接口UserService在接口中同样定义一个save()的方法,代码如下:
package com.cn.annotation;
public interface UserService {
public void save();
}
4.创建UserService接口的实现类UserServiceImpl,该类需要实现接口中的save方法代码如下:
package com.cn.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService{
@Resource(name="userDao")
private UserDao userDao;
public void save() {
this.userDao.save();
System.out.println("userservice...save...");
}
}
如上所示,首先使用@Service注解将UserServiceImpl类标识为Spring中的Bean,这相当于配置文件中<bean="userService" class="com.cn.annotation.UserServiceImpl"/>的编写;然后使用@Resource注解标注在属性userDao上,这相当于配置文件中<property name="userDao" ref="userDao"/>的写法。
5.创建控制器类UserController,编辑后如下所示:
package com.cn.annotation;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
@Controller("userController")
public class UserController {
@Resource(name="userService")
private UserService userService;
public void save() {
this.userService.save();
System.out.println("userController...save...");
}
}
6.创建配置文件AnnotationBean.xml,配置中编写基于Annotation装配的代码,如下:
<?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">
<!-- 使用context命名空间,在配置文件中开启相应的注解处理器 -->
<context:annotation-config>
<!-- 分别定义3个Bean实例 -->
<bean id="userDao" class="com.cn.annotation.UserDaoImpl"/>
<bean id="userService" class="com.cn.annotation.UserServiceImpl"/>
<bean id="userController" class="com.cn.annotation.UserController"/>
</context:annotation-config>
</beans>
上述Spring配置文件中的注解方式虽然较大程度简化了XML文件中Bean的配置,但仍需要在Spring配置文件中一一配置相应的Bean,为此Spring注解提供了另外一种高效的注解配置方式(对包路径下的所有Bean文件进行扫描),其配置如下:
<context:component-scan base-package="Bean 所在的包路径"/>
所以上述配置中<context:annotation-config></context:annotation-config>
及其内容都可替换为<context:component-scan base-package="com.cn.annotation"/>
(推荐使用这个)
注意:Spring 4.0以上版本
使用上面的代码对指定包中的注解进行扫描时,需要先向项目中导入spring-aop-4.3.6.RELEASE.jar
,否则程序在运行时会报错!
7.创建测试类AnnotationAssembleTest类,然后通过Spring容器加载配置文件获取UserController实例,最后调用示例中的save()方法,代码如下:
package com.cn.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnotationAssembleTest {
@org.junit.Test
public void Test() {
ApplicationContext appc = new ClassPathXmlApplicationContext("AnnotationBean.xml");
//获取UserController实例
UserController userController = appc.getBean("userController",UserController.class);
userController.save();
}
}
运行结果如下:
自动装配
Spring的<bean>元素包含一个autowire属性,我们可以通过设置autowire属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动地注入到其他Bean的Property中。
autowire属性有5个值,如下所示:
属性值 | 说明 |
---|---|
default(默认值) | 由<bean>的default-autowire 属性值确定。例如<beans default-autowire="byName">,则该<bean>元素中的autowire属性对应的属性值就为byName |
byName | 根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean,并将其属性自动装配 |
byType | 根据属性的数据类型(Type)自动装配,如果一个Bean的数据类型,兼容另一个Bean中属性的数据类型,则自动装配 |
constructor | 根据构造函数参数的数据类型,进行byType模式的自动装配 |
no | 在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义 |
下面简单几步演示如何自动装配
1.修改上面UserServiceImpl文件和UserController,分别在文件中增加雷属性的setter()方法
2.修改配置文件AnnotationBean.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: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元素的autowire属性完成自动装配 -->
<bean id="userDao" class="com.cn.annotation.UserDaoImpl"/>
<bean id="userService" class="com.cn.annotation.UserServiceImpl" autowire="byName"/>
<bean id="userController" class="com.cn.annotation.UserController" autowire="byName"/>
</beans>
在默认情况下,配置文件中需要通过ref来装配Bean,但设置autowire="byName"后,Spring会自动寻找userServiceBean中的属性,并将其属性名称与配置文件中定义的Bean做匹配,由于UserServiceImpl中定义了userDao属性及其setter方法,这与配置文件中id为userDao的Bean相匹配,所以Spring会自动地将id为userDao的Bean装配到id为userService的Bean中。
运行结果如下图所示: