• Spring:IOC/DI注解开发(7)


    常用注解总结https://blog.csdn.net/qq_43751200/article/details/127639586

    注解开发定义bean

    演示环境准备

    • 创建一个Maven项目

    • pom.xml添加Spring的依赖

      <dependencies>
          <dependency>
              <groupId>org.springframeworkgroupId>
              <artifactId>spring-contextartifactId>
              <version>5.2.10.RELEASEversion>
          dependency>
      dependencies>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • resources下添加applicationContext.xml

      
      <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="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
      beans>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类

      public interface BookDao {
          public void save();
      }
      public class BookDaoImpl implements BookDao {
          public void save() {
              System.out.println("book dao save ..." );
          }
      }
      public interface BookService {
          public void save();
      }
      
      public class BookServiceImpl implements BookService {
          public void save() {
              System.out.println("book service save ...");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    步骤1:删除原来的XML配置

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

    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    
    • 1

    步骤2:在Dao上添加注解@Component

    只能在实体类(能够new对象)上才能添加注解,接口不可以添加

    在这里插入图片描述

    注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。

    XML与注解配置的对应关系

    在这里插入图片描述

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

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

    在这里插入图片描述

    说明:

    component-scan

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

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

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

    步骤4:运行程序

    在这里插入图片描述

    步骤5:Service上添加注解

    在BookServiceImpl类上也添加@Component交给Spring框架管理, 但是不对该类取别名。

    @Component
    public class BookServiceImpl implements BookService {
        private BookDao bookDao;
    
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    步骤6:运行程序

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

    @Component
    public class BookServiceImpl implements BookService {
    
        @Override
        public void save() {
            System.out.println("----------------------");
            System.out.println("book service save ...");
            System.out.println("----------------------");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    注解开发定义bean总结

    对于@Component注解,还衍生出了其他三个注解@Controller@Service@Repository

    在这里插入图片描述

    这三个注解和@Component注解的作用是一样的,为了方便后期在编写类的时候能很好的区分出这个类是属于表现层业务层还是数据层的类。

    @Component等

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



    纯注解开发模式

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

    • Spring3.0开启了纯注解开发模式,使用Java类替代配置文件(也就是把配置文件applicationContext.xml去掉),开启了Spring快速开发赛道

    纯注解开发步骤1:创建配置类

    创建一个配置类SpringConfig

    在这里插入图片描述

    纯注解开发步骤2:标识该类为配置类

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

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

    纯注解开发步骤3:创建配置类

    在配置类上添加包扫描注解@ComponentScan替换

    @Configuration  // 配置类注解
    @ComponentScan("com.itheima")   // 在配置类上添加包扫描注解
    public class SpringConfig {
    }
    
    • 1
    • 2
    • 3
    • 4

    纯注解开发步骤4:创建运行类并执行

    public class AppForAnnotation {
    
        public static void main(String[] args) {
            ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            System.out.println(bookDao);
            BookService bookService = ctx.getBean(BookService.class);
            System.out.println(bookService);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    纯注解开发模式总结

    纯注解开发主要内容

    • Java类替换Spring核心配置文件

    在这里插入图片描述

    • @Configuration注解用于设定当前类为配置类

    • @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

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

      -- ClassPathXmlApplicationContext是加载XML配置文件 --
      ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
      
      -- AnnotationConfigApplicationContext是加载配置类 --
      ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
      
      • 1
      • 2
      • 3
      • 4
      • 5

    @Configuration

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

    @ComponentScan

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



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

    Bean的作用范围

    单例:注解配置@Scope(“singleton”)

    在这里插入图片描述

    非单例:注解配置@Scope(“prototype”)

    在这里插入图片描述

    @Scope

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

    Bean的生命周期

    在这里插入图片描述

    在这里插入图片描述

    知识点1:@PostConstruct

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

    知识点2:@PreDestroy

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

    小结

    注意:@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包, 从JDK9以后jdk中的javax.annotation包被移除了,这两个注解刚好就在这个包中。

    <dependency>
      <groupId>javax.annotationgroupId>
      <artifactId>javax.annotation-apiartifactId>
      <version>1.3.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5



    注解开发依赖注入

    • Spring为了使用注解简化开发,并没有提供构造函数注入setter注入对应的注解,只提供了自动装配的注解实现。

    环境准备

    • 创建一个Maven项目

    • pom.xml添加Spring的依赖

        <dependencies>
      	      <dependency>
      	          <groupId>org.springframeworkgroupId>
      	          <artifactId>spring-contextartifactId>
      	          <version>5.2.10.RELEASEversion>
      	      dependency>
      	  dependencies>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 添加一个配置类SpringConfig

      @Configuration
      @ComponentScan("com.itheima")
      public class SpringConfig {
      }
      
      • 1
      • 2
      • 3
      • 4
    • 添加BookDao、BookDaoImpl、BookService、BookServiceImpl类

      public interface BookDao {
          public void save();
      }
      @Repository
      public class BookDaoImpl implements BookDao {
          public void save() {
              System.out.println("book dao save ..." );
          }
      }
      public interface BookService {
          public void save();
      }
      @Service
      public class BookServiceImpl implements BookService {
          private BookDao bookDao;
      	public void setBookDao(BookDao bookDao) {
              this.bookDao = bookDao;
          }
          public void save() {
              System.out.println("book service save ...");
              bookDao.save();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    • 创建运行类APP

      public class App {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
              BookService bookService = ctx.getBean(BookService.class);
              bookService.save();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 报错,bookDao为空指针
      在这里插入图片描述

    引用类型注入

    注解实现按照类型注入

    在BookServiceImpl类的bookDao属性上添加@Autowired注解

    @Service("bookService")
    public class BookServiceImpl implements BookService {
        
        @Autowired
        private BookDao bookDao;
    
    //    public void setBookDao(BookDao bookDao) {
    //        this.bookDao = bookDao;
    //    }
    
        @Override
        public void save() {
            System.out.println("book service ...");
            bookDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注意:

    • @Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是写在属性上并将setter方法删除掉
    • 为什么setter方法可以删除呢?
      • 自动装配基于反射设计创建对象并通过暴力反射为私有属性进行设值
      • 普通反射只能获取public修饰的内容
      • 暴力反射除了获取public修饰的内容还可以获取private修改的内容
      • 所以此处无需提供setter方法

    问题提出: 如果我这里再建一个类BookDaoImpl2来实现BookDao,运行结果咋么样???

    在这里插入图片描述

    运行结果:报错NoUniqueBeanDefinitionException在这里插入图片描述

    如何解决呢?

    • 下面的按照名称注入就可以解决上述问题

    注解实现按照名称注入

    当根据类型在容器中找到多个bean, 注入参数的属性名又和容器中bean的名称不一致,这个时候该如何解决,就需要使用到@Qualifier来指定注入哪个名称的bean对象。

    @Qualifier注解后的值就是需要注入的bean的名称。

    注意:@Qualifier不能独立使用,必须和@Autowired一起使用

    指定BookDaoImpl类

    在这里插入图片描述

    指定BookDaoImpl2类

    在这里插入图片描述

    普通类型注入

    简单类型注入的是基本数据类型或者字符串类型,下面在BookDaoImpl类中添加一个name属性,用其进行简单类型注入

    @Repository("bookDao")
    public class BookDaoImpl implements BookDao {
        @Value("lsm")
        private String username;
        @Value("1000")
        private int connectCounts;
        @Override
        public void save() {
            System.out.println("book dao save ..." + username +", " + connectCounts);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行结果

    在这里插入图片描述

    注解读取proterties配置文件

    @Value一般会被用在从properties配置文件中读取内容进行使用

    步骤1:resource下准备properties文件

    在这里插入图片描述

    步骤2: 使用注解加载properties配置文件

    在配置类上添加@PropertySource注解,加载配置文件

    @Configuration
    @ComponentScan("com.itheima")
    @PropertySource({"jdbc.properties", "msg.properties"})  
    public class SpringConfig {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    步骤3:使用@Value读取配置文件中的内容

    @Repository("bookDao")
    public class BookDaoImpl implements BookDao {
        @Value("${username}")   // 使用Value读取properties配置文件中的值
        private String username;
    
        @Value("${connectCounts}")
        private int connectCounts;
        @Override
        public void save() {
            System.out.println("book dao save ..." + username +", " + connectCounts);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    步骤4:运行程序

    在这里插入图片描述

    这里输出的username不正确,是系统的username,注解的解决方法暂时没有找到,XML配置文件的方式解决方案如下:

    
    <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:property-placeholder location="jdbc.properties,jdbc2.properties" system-properties-mode="NEVER"/>   
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:

    • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个

      @PropertySource({"jdbc.properties","xxx.properties"})
      
      • 1
    • @PropertySource注解属性中不支持使用通配符*,运行会报错

      @PropertySource({"*.properties"})
      
      • 1
    • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文件

      @PropertySource({"classpath:jdbc.properties"})
      
      • 1



    注解开发总结

    XML配置和注解之间的对比

    在这里插入图片描述

  • 相关阅读:
    【考研复习】《操作系统原理》孟庆昌等编著课后习题+答案——第四章
    【刷题系列】顺序表OJ题
    字节跳动算法岗面试,问的贼细!
    《绿色消费实施方案》的推出,释放出怎么样的信号,有无新的赛道
    【牛客网-前端笔试题】——vue专项练习
    如何完成网课答案公众号搭建?小白教程!内附网课题库接口!
    【漏洞复现】Apache_Tomcat_PUT方法任意写文件(CVE-2017-12615)
    K8S 1.20 弃用 Docker 评估之 Docker CLI 的替代产品
    运行的 akrun 会打印信息到控制台,如何取消打印 -- chatGPT
    React介绍
  • 原文地址:https://blog.csdn.net/qq_43751200/article/details/127628384