Spring项目IOC/DI注解开发

素颜马尾好姑娘i 2024-04-01 09:35 146阅读 0赞

Spring的IOC/DI对应的配置开发使用起来相对来说还是比较复杂的,复杂的地方在配置文件。
前面Spring的时候说过,Spring可以简化代码的开发,到现在并没有体会到。
所以Spring到底是如何简化代码开发的呢?
要想真正简化开发,就需要用到Spring的注解开发,Spring对注解支持的版本历程:

  • 2.0版开始支持注解
  • 2.5版注解功能趋于完善
  • 3.0版支持纯注解开发

关于注解开发,我们会讲解两块内容注解开发定义bean纯注解开发
注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解。

1. 环境准备

注解开发之前,先来准备下案例环境:

  • 创建一个Maven项目
  • pom.xml添加Spring的依赖

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework</groupId>
    4. <artifactId>spring-context</artifactId>
    5. <version>5.2.15.RELEASE</version>
    6. </dependency>
    7. </dependencies>
  • resources下添加applicationContext.xml

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <beans xmlns="http://www.springframework.org/schema/beans"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    5. <bean id="userDao" class="com.dcxuexi.dao.impl.UserDaoImpl" />
    6. </beans>
  • 添加UserDao、UserDaoImpl、UserService、UserServiceImpl类

    1. public interface UserDao {
    2. public void select();
    3. }
    4. public class UserDaoImpl implements UserDao {
    5. public void select() {
    6. System.out.println("UserDao select , running ......");
    7. }
    8. }
    9. public interface UserService {
    10. public void select();
    11. }
    12. public class UserServiceImpl implements UserService {
    13. public void select() {
    14. System.out.println("UserService select, running ......");
    15. }
    16. }
  • 创建运行类SpringAnnotation

    1. public class SpringAnnotation {
    2. public static void main(String[] args) {
    3. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    4. UserDao userDao = context.getBean("userDao", UserDao.class);
    5. userDao.select();
    6. }
    7. }

最终创建好的项目结构如下:
在这里插入图片描述

2. 注解开发定义bean

在上述环境的基础上,我们来学一学Spring是如何通过注解实现bean的定义开发?

步骤1:删除原XML配置

将配置文件中的<bean>标签删除掉

  1. <bean id="userDao" class="com.dcxuexi.dao.impl.UserDaoImpl" />

步骤2:Dao上添加注解

在UserDaoImpl类上添加@Component注解

  1. @Component("userDao")
  2. public class UserDaoImpl implements UserDao {
  3. public void select() {
  4. System.out.println("UserDao select , running ......");
  5. }
  6. }

注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。
XML与注解配置的对应关系:
在这里插入图片描述

步骤3:配置Spring的注解包扫描

为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <!-- <bean id="userDao" class="com.dcxuexi.dao.impl.UserDaoImpl" />-->
  7. <context:component-scan base-package="com.dcxuexi" />
  8. </beans>

说明:
component-scan

  • component:组件,Spring将管理的bean视作自己的一个组件
  • scan:扫描

base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。

  • 包路径越多[如:com.dcxuexi.dao.impl],扫描的范围越小速度越快
  • 包路径越少[如:com.dcxuexi],扫描的范围越大速度越慢
  • 一般扫描到项目的组织名称即Maven的groupId下[如:com.dcxuexi]即可。

步骤4:运行程序

运行SpringAnnotation类查看打印结果
在这里插入图片描述

步骤5:Service上添加注解

在UserServiceImpl类上也添加@Component交给Spring框架管理

  1. @Component("userService")
  2. public class UserServiceImpl implements UserService {
  3. private UserDao userDao;
  4. public void setUserDao(UserDao userDao) {
  5. this.userDao = userDao;
  6. }
  7. public void select() {
  8. System.out.println("UserService select, running ......");
  9. userDao.select();
  10. }
  11. }

步骤6:运行程序

在SpringAnnotation类中,从IOC容器中获取UserServiceImpl对应的bean对象,打印

  1. public class SpringAnnotation {
  2. public static void main(String[] args) {
  3. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  4. UserDao userDao = context.getBean("userDao", UserDao.class);
  5. //userDao.select();
  6. System.out.println(userDao);
  7. //按类型获取bean
  8. UserService userService = context.getBean(UserService.class);
  9. //userService.select();
  10. System.out.println(userService);
  11. }
  12. }

打印观察结果,两个bean对象都已经打印到控制台
在这里插入图片描述
说明:

  • UserServiceImpl类没有起名称,所以在App中是按照类型来获取bean对象
  • @Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取,如

    1. UserService userService = (UserService) context.getBean("userServiceImpl");
    2. System.out.println(userService);

对于@Component注解,还衍生出了其他三个注解@Controller@Service@Repository
通过查看源码会发现:
在这里插入图片描述
这三个注解和@Component注解的作用是一样的,为什么要衍生出这三个呢?
方便我们后期在编写类的时候能很好的区分出这个类是属于表现层业务层还是数据层的类。

知识点1:@Component等


























名称 @Component/@Controller/@Service/@Repository
类型 类注解
位置 类定义上方
作用 设置该类为spring管理的bean
属性 value(默认):定义bean的id

3. 纯注解开发模式

上面已经可以使用注解来配置bean,但是依然有用到配置文件,在配置文件中对包进行了扫描,Spring在3.0版已经支持纯注解开发

  • Spring3.0开启了纯注解开发模式,使用Java类替代配置文件,开启了Spring快速开发赛道

具体如何实现?

3.1 思路分析

实现思路为:

  • 将配置文件applicationContext.xml删除掉,使用类来替换。

3.2 实现步骤

步骤1:创建配置类

创建一个配置类SpringConfig

  1. public class SpringConfig {
  2. }

步骤2:标识该类为配置类

在配置类上添加@Configuration注解,将其标识为一个配置类,替换applicationContext.xml

  1. @Configuration
  2. public class SpringConfig {
  3. }

步骤3:用注解替换包扫描配置

在配置类上添加包扫描注解@ComponentScan替换<context:component-scan base-package=""/>

  1. @Configuration
  2. @ComponentScan("com.dcxuexi")
  3. public class SpringConfig {
  4. }

步骤4:创建运行类并执行

创建一个新的运行类SpringConfigAnnotation

  1. public class SpringConfigAnnotation {
  2. public static void main(String[] args) {
  3. ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
  4. UserDao userDao = context.getBean(UserDao.class);
  5. System.out.println(userDao);
  6. UserService userService = context.getBean(UserService.class);
  7. System.out.println(userService);
  8. }
  9. }

运行SpringConfigAnnotation,可以看到两个对象依然被获取成功
在这里插入图片描述
至此,纯注解开发的方式就已经完成了,主要内容包括:

  • Java类替换Spring核心配置文件
    在这里插入图片描述
  • @Configuration注解用于设定当前类为配置类
  • @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

    1. @ComponentScan({
    2. "com.dcxuexi.dao","com.dcxuexi.service"})
  • 读取Spring核心配置文件初始化容器对象切换为读取Java配置类初始化容器对象

    1. //加载配置文件初始化容器
    2. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    3. //加载配置类初始化容器
    4. ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

知识点1:@Configuration


























名称 @Configuration
类型 类注解
位置 类定义上方
作用 设置该类为spring配置类
属性 value(默认):定义bean的id

知识点2:@ComponentScan


























名称 @ComponentScan
类型 类注解
位置 类定义上方
作用 设置spring配置类扫描路径,用于加载使用注解格式定义的bean
属性 value(默认):扫描路径,此路径可以逐层向下扫描

小结:
这一节重点掌握的是使用注解完成Spring的bean管理,需要掌握的内容为:

  • 记住@Component、@Controller、@Service、@Repository这四个注解
  • applicationContext.xml中<context:component-san/>的作用是指定扫描包路径,注解为@ComponentScan
  • @Configuration标识该类为配置类,使用类替换applicationContext.xml文件
  • ClassPathXmlApplicationContext是加载XML配置文件
  • AnnotationConfigApplicationContext是加载配置类

4. 注解开发bean作用范围与生命周期管理

使用注解已经完成了bean的管理,接下来按照前面所学习的内容,将通过配置实现的内容都换成对应的注解实现,包含两部分内容:bean作用范围bean生命周期

4.1 环境准备

先来准备环境:

  • 创建一个Maven项目
  • pom.xml添加Spring的依赖

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework</groupId>
    4. <artifactId>spring-context</artifactId>
    5. <version>5.2.15.RELEASE</version>
    6. </dependency>
    7. </dependencies>
  • 添加一个配置类SpringConfig

    1. @Configuration
    2. @ComponentScan("com.dcxuexi")
    3. public class SpringConfig {
    4. }
  • 添加UserDao、UserDaoImpl类

    1. public interface UserDao {
    2. public void select();
    3. }
    4. @Repository
    5. public class UserDaoImpl implements UserDao {
    6. public void select() {
    7. System.out.println("UserDao select, running ......");
    8. }
    9. }
  • 创建运行类SpringAnnotationBean

    1. public class SpringAnnotationBean {
    2. public static void main(String[] args) {
    3. ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
    4. UserDao userDao = context.getBean(UserDao.class);
    5. UserDao userDao2 = context.getBean(UserDao.class);
    6. System.out.println(userDao);
    7. System.out.println(userDao2);
    8. }
    9. }

最终创建好的项目结构如下:
在这里插入图片描述

4.2 Bean的作用范围

(1)先运行SpringAnnotationBean类,在控制台打印两个一摸一样的地址,说明默认情况下bean是单例
在这里插入图片描述
(2)要想将UserDaoImpl变成非单例,只需要在其类上添加@scope注解

  1. @Repository
  2. //@Scope设置bean的作用范围
  3. @Scope("prototype")
  4. public class UserDaoImpl implements UserDao {
  5. public void select() {
  6. System.out.println("UserDao select, running ......");
  7. }
  8. }

再次执行SpringAnnotationBean类,打印结果:
在这里插入图片描述

知识点1:@Scope


























名称 @Scope
类型 类注解
位置 类定义上方
作用 设置该类创建对象的作用范围
可用于设置创建出的bean是否为单例对象
属性 value(默认):定义bean作用范围,
默认值singleton(单例),可选值prototype(非单例)

4.3 Bean的生命周期

(1)在UserDaoImpl中添加两个方法,initdestroy,方法名可以任意

  1. @Repository
  2. //@Scope设置bean的作用范围
  3. //@Scope("prototype")
  4. public class UserDaoImpl implements UserDao {
  5. public void select() {
  6. System.out.println("UserDao select, running ......");
  7. }
  8. public void init() {
  9. System.out.println("UserDao init ...");
  10. }
  11. public void destroy() {
  12. System.out.println("UserDao destroy ...");
  13. }
  14. }

(2)如何对方法进行标识,哪个是初始化方法,哪个是销毁方法?
只需要在对应的方法上添加@PostConstruct@PreDestroy注解即可。

  1. @Repository
  2. //@Scope设置bean的作用范围
  3. //@Scope("prototype")
  4. public class UserDaoImpl implements UserDao {
  5. public void select() {
  6. System.out.println("UserDao select, running ......");
  7. }
  8. @PostConstruct //在构造方法之后执行,替换 init-method
  9. public void init() {
  10. System.out.println("UserDao init ...");
  11. }
  12. @PreDestroy //在销毁方法之前执行,替换 destroy-method
  13. public void destroy() {
  14. System.out.println("UserDao destroy ...");
  15. }
  16. }

(3)要想看到两个方法执行,需要注意的是destroy只有在容器关闭的时候,才会执行,所以需要修改SpringAnnotationBean的类

  1. public class SpringAnnotationBean {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
  4. UserDao userDao = context.getBean(UserDao.class);
  5. UserDao userDao2 = context.getBean(UserDao.class);
  6. System.out.println(userDao);
  7. System.out.println(userDao2);
  8. context.close(); //关闭容器
  9. }
  10. }

(4)运行SpringAnnotationBean类查看打印结果,证明init和destroy方法都被执行了。
在这里插入图片描述
注意:@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包

  1. <dependency>
  2. <groupId>javax.annotation</groupId>
  3. <artifactId>javax.annotation-api</artifactId>
  4. <version>1.3.2</version>
  5. </dependency>

找不到的原因是,从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。

知识点1:@PostConstruct


























名称 @PostConstruct
类型 方法注解
位置 方法上
作用 设置该方法为初始化方法
属性

知识点2:@PreDestroy


























名称 @PreDestroy
类型 方法注解
位置 方法上
作用 设置该方法为销毁方法
属性

小结
在这里插入图片描述

项目代码

  • gitee 代码下载
  • github 代码代码

发表评论

表情:
评论列表 (有 0 条评论,146人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring 注解开发

    spring 注解开发 注解:为了代替配置文件,让配置信息和java代码看起来更直观 (注,JDK1.8和spring4.0以上才兼容) 也起解释说明和检查的作用,