目录
任务描述
相关知识
基于注解的 Bean 装配背景
常用的注解
基于注解的 Bean 装配实例
创建 DAO 层接口
创建 DAO 层接口的实现类
创建 Service 层接口
创建 Service 层接口的实现类
创建 Controller 层 StudentAction 类
创建 Spring 配置文件
创建测试类
编程要求
测试说明
参考答案
本关任务:使用基于注解的 Bean 装配使给定程序正确运行。
为了完成本关任务,你需要掌握: 1.基于注解的 Bean 装配背景; 2.常用的注解。
在 Spring 中,尽管使用 XML 配置文件可以实现 Bean 的装配工作,但如果配置文件中 Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。因此,基于注解的 Bean 装配应运而生。
下表列出了常用的注解:
注解 | 说明 |
---|---|
@Component 注解 | 该注解可以作用在任何层次(Dao 层、Controller 层等),它用来描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),使用时只需将该注解标注在相应类上。 |
@Repository 注解 | 该注解通常作用在数据访问层(DAO 层),用来标识 Spring 中的 Bean,其功能与 @Component 相同。 |
@Service 注解 | 该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Controller 注解 | 该注解通常作用在控制层,用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。 |
@Autowired 注解 | 用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。 |
@Resource 注解 | 其作用与 Autowired 一样。其区别在于 @Autowired 默认按照 Bean 类型装配,而 @Resource 默认按照 Bean 实例名称进行装配,该注解有两个重要属性:name 和 type。Spring 将 name 属性解析为 Bean 实例名称,type 属性解析为 Bean 实例类型。如果指定 name 属性,则按实例名称进行装配;如果指定 type 属性,则按 Bean 类型进行装配。如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,则再按照 Bean 类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。 |
创建一个 Spring 项目,在该项目的 src 目录下创建一个名为 com.educoder.springtest 的包,在该包下创建一个名为 StudentDao 的接口,并添加一个 show() 方法,如下所示。
package com.educoder.springtest;
// 创建 StudentDao 接口
public interface StudentDao {
// 创建 show 方法
public void show();
}
在 com.educoder.springtest 包下创建 StudentDao 接口的实现类 StudentDaoImpl,编辑后如下所示。
package com.educoder.springtest;
import org.springframework.stereotype.Repository;
@Repository("studentDao")
public class StudentDaoImpl implements StudentDao{
// 重写 show 方法
@Override
public void show() {
System.out.println("执行Dao层的show()方法");
}
}
上述代码中,首先使用了 @Repository 注解将 StudentDaoImpl 类标识为 Spring 中的 Bean,其相当于在配置文件中添加
。然后重写了 show() 方法,并输出提示语,用于验证是否成功调用了该方法。
在 com.educoder.springtest 包下创建一个名为 StudentService 的接口,并添加一个 show() 方法,如下所示。
package com.educoder.springtest;
// 创建 StudentDao 接口
public interface StudentService {
// 创建 show 方法
public void show();
}
在 com.educoder.springtest 包下创建 StudentService 接口的实现类 StudentServiceImpl,编辑后如下所示。
package com.educoder.springtest;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("studentService")
public class StudentServiceImpl implements StudentService {
@Resource(name = "studentDao")
private StudentDao studentDao;
public StudentDao getStudentDao() {
return studentDao;
}
public void setStudentDao(StudentDao studentDao){
this.studentDao=studentDao;
}
// 重写 show 方法
@Override
public void show() {
// 调用 studentDao 中的 show()方法
studentDao.show();
System.out.println("Service层的show()方法执行了");
}
}
上述代码中,首先使用了 @Service 注解将 StudentServiceImpl 类标识为 Spring 中的 Bean,其相当于在配置文件中添加
。然后使用 @Resource 注解标注在属性 studentDao 上,这相当于在配置文件中添加
。最后在该类的 show() 方法中调用 studentDao 中的 show() 方法,并输出提示语。
在 com.educoder.springtest 包下创建一个名为 StudentAction 的类,编辑后如下所示。
package com.educoder.springtest;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
@Controller("studentAction")
public class StudentAction {
@Resource(name = "studentService")
private StudentService studentService;
public StudentService getStudentService() {
return studentService;
}
public void setStudentService(StudentService studentService ){
this.studentService=studentService;
}
public void show() {
// 调用 studentService 中的 show() 方法
studentService.show();
System.out.println("Action层的show()方法执行了");
}
}
上述代码中,首先使用 @Controller 注解标注 StudentAction 类,其写法相当于在配置文件中添加
。然后使用了 @Resource 注解标注在 studentService 上,这相当于在配置文件内添加
。最后在其 show() 方法中调用了 studentService 中的 show() 方法,并输出提示语。
在 com.educoder.springtest 包下创建一个名为 applicationContext.xml 的配置文件,文件内容如下所示。
与之前的配置文件相比,上述代码的 beans 元素中增加了第 7 行、第 15 行和第 16 行中包含有 context 的代码,然后在第 18 行代码中,使用 context 命名空间的 component-scan 元素进行注解的扫描,其 base-package 属性用于通知 spring 所需要扫描的目录。
在 com.educoder.springtest 包下创建一个名为 MyTest 的测试类,编辑后如下所示。
package com.educoder.springtest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 定义 Spring 配置文件路径
String xmlPath = "com/educoder/springtest/applicationContext.xml";
// 初始化 Spring 容器,加载配置文件,并对 bean 进行实例化
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
// 获得 studentAction 实例
StudentAction studentAction = (StudentAction) applicationContext.getBean("studentAction");
// 调用 studentAction 中的 show() 方法
studentAction.show();
}
}
上述代码中,首先通过加载配置文件并获取 studentAction 的实例,然后调用该实例的 show() 方法。从输出结果中可以看出,DAO 层、Service 层和 Action 层的 show() 方法都成功输出了结果。由此可知,基于注解装配 Bean 的方式已经成功实现了。
执行结果:
执行Dao层的show()方法
执行Service层的show()方法
执行Action层的show()方法
仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写代码,使用基于注解的 Bean 装配使给定程序正确运行,部分说明及要求如下:
程序会在后台获得 studentAction 实例,并调用 show() 方法,在该方法中会调用 studentServiceImpl 实例的 toTime()方法,该方法又会调用 studentDaoImpl 实例的 showTables()方法;
在指定文件(StudentDaoImpl.java、StudentServiceImpl.java、StudentAction.java)的指定位置补充注解使程序运行,所有代码文件可在右侧代码编辑区的“代码文件”处可见。
平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。
可在右侧 “测试结果”区查看具体的测试集详情。 测试输入: 无 预期输出:
执行Dao层的showTables()方法
执行Service层的toTime()方法
执行Action层的show()方法
开始你的任务吧,祝你成功!
StudentDaoImpl.java
package com.educoder.springtest;
import org.springframework.stereotype.Repository;
// 请在此处编写代码
/********* Begin *********/
@Repository("studentDao")
/********* End *********/
public class StudentDaoImpl implements StudentDao{
// 重写 showTables 方法
@Override
public void showTables() {
System.out.println("执行Dao层的showTables()方法");
}
}
StudentServiceImpl.java
package com.educoder.springtest;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
// 请在此处编写代码
/********* Begin *********/
@Service("studentService")
/********* End *********/
public class StudentServiceImpl implements StudentService {
// 请在此处编写代码
/********* Begin *********/
@Resource(name = "studentDao")
/********* End *********/
private StudentDao studentDao;
public StudentDao getStudentDao() {
return studentDao;
}
public void setStudentDao(StudentDao studentDao){
this.studentDao=studentDao;
}
// 重写 toTime 方法
@Override
public void toTime() {
// 调用 studentDao 中的 showTables() 方法
studentDao.showTables();
System.out.println("执行Service层的toTime()方法");
}
}
StudentAction.java
package com.educoder.springtest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
// 请在此处编写代码
/********* Begin *********/
@Controller("studentAction")
/********* End *********/
public class StudentAction {
// 请在此处编写代码
/********* Begin *********/
@Resource(name = "studentService")
/********* End *********/
private StudentService studentService;
public StudentService getStudentService() {
return studentService;
}
public void setStudentService(StudentService studentService ){
this.studentService=studentService;
}
public void show() {
// 调用 personService 中的 toTime() 方法
studentService.toTime();
System.out.println("执行Action层的show()方法");
}
}