Spring Bean的装配方式 第2关:基于注解的 Bean 装配

28 篇文章 9 订阅

目录

任务描述

相关知识

基于注解的 Bean 装配背景

常用的注解

基于注解的 Bean 装配实例

创建 DAO 层接口

创建 DAO 层接口的实现类

创建 Service 层接口

创建 Service 层接口的实现类

创建 Controller 层 StudentAction 类

创建 Spring 配置文件

创建测试类

编程要求

测试说明

参考答案


任务描述

本关任务:使用基于注解的 Bean 装配使给定程序正确运行。

相关知识

为了完成本关任务,你需要掌握: 1.基于注解的 Bean 装配背景; 2.常用的注解。

基于注解的 Bean 装配背景

在 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 异常。

基于注解的 Bean 装配实例

创建 DAO 层接口

创建一个 Spring 项目,在该项目的 src 目录下创建一个名为 com.educoder.springtest 的包,在该包下创建一个名为 StudentDao 的接口,并添加一个 show() 方法,如下所示。

package com.educoder.springtest;
// 创建 StudentDao 接口
public interface StudentDao {
    // 创建 show 方法
    public void show();
}

创建 DAO 层接口的实现类

在 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,其相当于在配置文件中添加 <bean id="studentDao"class="com.educoder.springtest.StudentDaoImpl"/> 。然后重写了 show() 方法,并输出提示语,用于验证是否成功调用了该方法。

创建 Service 层接口

在 com.educoder.springtest 包下创建一个名为 StudentService 的接口,并添加一个 show() 方法,如下所示。

package com.educoder.springtest;
// 创建 StudentDao 接口
public interface StudentService {
    // 创建 show 方法
    public void show();
}

创建 Service 层接口的实现类

在 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,其相当于在配置文件中添加 <bean id="studentService"class="com.educoder.springtest.StudentServiceImpl"/> 。然后使用 @Resource 注解标注在属性 studentDao 上,这相当于在配置文件中添加<property name="personDao"ref="personDao"/> 。最后在该类的 show() 方法中调用 studentDao 中的 show() 方法,并输出提示语。

创建 Controller 层 StudentAction 类

在 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 类,其写法相当于在配置文件中添加 <bean id="studentAction"class="com.educoder.springtest.StudentAction"/>。然后使用了 @Resource 注解标注在 studentService 上,这相当于在配置文件内添加 <property name="studentService"ref="studentService"/>。最后在其 show() 方法中调用了 studentService 中的 show() 方法,并输出提示语。

创建 Spring 配置文件

在 com.educoder.springtest 包下创建一个名为 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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    <!--使用context命名空间,通知spring扫描指定目录,进行注解的解析-->
    <context:component-scan base-package="com.educoder.springtest"/>
</beans>

与之前的配置文件相比,上述代码的 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 的方式已经成功实现了。

执行结果:

  1. 执行Dao层的show()方法
  2. 执行Service层的show()方法
  3. 执行Action层的show()方法

编程要求

仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写代码,使用基于注解的 Bean 装配使给定程序正确运行,部分说明及要求如下:

  • 程序会在后台获得 studentAction 实例,并调用 show() 方法,在该方法中会调用 studentServiceImpl 实例的 toTime()方法,该方法又会调用 studentDaoImpl 实例的 showTables()方法;

  • 在指定文件(StudentDaoImpl.java、StudentServiceImpl.java、StudentAction.java)的指定位置补充注解使程序运行,所有代码文件可在右侧代码编辑区的“代码文件”处可见。

测试说明

平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。

可在右侧 “测试结果”区查看具体的测试集详情。 测试输入: 无 预期输出:

  1. 执行Dao层的showTables()方法
  2. 执行Service层的toTime()方法
  3. 执行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()方法");
    }
}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

于建章

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值