通过注解装配 Bean

1、前言

优势

1.可以减少 XML 的配置,当配置项多的时候,XML配置过多会导致项目臃肿难以维护

2.功能更加强大,既能实现 XML 的功能,也提供了自动装配的功能,采用了自动装配后,程序猿所需要做的决断就少了,更加有利于对程序的开发,这就是“约定优于配置”的开发原则

IOC发现Bean的两种方式

组件扫描:通过定义资源的方式,让 Spring IoC 容器扫描对应的包,从而把 bean 装配进来。

自动装配:通过注解定义,使得一些依赖关系可以通过注解完成。

注解分为两类

  一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

  一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

2、使用@Compoent 装配 Bean

我们把之前创建的 Student 类改一下:

package pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component(value = "student1")
public class Student { @Value("1")
int id;
@Value("student_name_1")
String name; // getter and setter
}

 解释一下:

@Component注解:

  表示 Spring IoC 会把这个类扫描成一个 bean 实例,而其中的 value 属性代表这个类在 Spring 中的 id,这就相当于在 XML 中定义的 Bean 的 id:<bean id="student1" class="pojo.Student" />,也可以简写成 @Component("student1"),甚至直接写成 @Component ,对于不写的,Spring IoC 容器就默认以类名来命名作为 id,只不过首字母小写,配置到容器中。

@Value注解:

  表示值的注入,跟在 XML 中写 value 属性是一样的。

    这样我们就声明好了我们要创建的一个 Bean,就像在 XML 中写下了这样一句话:

<bean name="student1" class="pojo.Student">
<property name="id" value="1" />
<property name="name" value="student_name_1"/>
</bean>

  但是现在我们声明了这个类,并不能进行任何的测试,因为 Spring IoC 并不知道这个 Bean 的存在,这个时候我们可以使用一个 StudentConfig 类去告诉 Spring IoC :

package pojo;
import org.springframework.context.annotation.ComponentScan; @ComponentScan
public class StudentConfig {
}

这个类十分简单,没有任何逻辑,但是需要说明两点:

1、该类和 Student 类位于同一包名下

2、@ComponentScan注解:

代表进行扫描,默认是扫描当前包的路径,扫描所有带有 @Component 注解的 POJO。

PS:也可以用XML来配置扫描路径,不过推荐使用注解的形式

  这样一来,我们就可以通过 Spring 定义好的 Spring IoC 容器的实现类——AnnotationConfigApplicationContext 去生成 IoC 容器了:

ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
Student student = (Student) context.getBean("student1", Student.class);
student.printInformation();

  这里可以看到使用了 AnnotationConfigApplicationContext 类去初始化 Spring IoC 容器,它的配置项是 StudentConfig 类,这样 Spring IoC 就会根据注解的配置去解析对应的资源,来生成 IoC 容器了。

明显的弊端:

  • 对于 @ComponentScan 注解,它只是扫描所在包的 Java 类,但是更多的时候我们希望的是可以扫描我们指定的类
  • 上面的例子只是注入了一些简单的值,测试发现,通过 @Value 注解并不能注入对象

@Component 注解存在着两个配置项:

basePackages:它是由 base 和 package 两个单词组成的,而 package 还是用了复数,意味着它可以配置一个 Java 包的数组,Spring 会根据它的配置扫描对应的包和子包,将配置好的 Bean 装配进来

basePackageClasses:它由 base、package 和 class 三个单词组成,采用复数,意味着它可以配置多个类, Spring 会根据配置的类所在的包,为包和子包进行扫描装配对应配置的 Bean

我们来试着重构之前写的 StudentConfig 类来验证上面两个配置项:

package pojo;
import org.springframework.context.annotation.ComponentScan; @ComponentScan(basePackages = "pojo")//配置扫描pojo包
public class StudentConfig {
} // —————————————————— 【 宇宙超级无敌分割线】——————————————————
package pojo; import org.springframework.context.annotation.ComponentScan; @ComponentScan(basePackageClasses = pojo.Student.class)//配置扫描pojo包下名为Student的类
public class StudentConfig {
}

对于 【basePackages】 和 【basePackageClasses】 的选择问题:

  【basePackages】 的可读性会更好一些,所以在项目中会优先选择使用它,但是在需要大量重构的工程中,尽量不要使用【basePackages】,因为很多时候重构修改包名需要反复地配置,而 IDE 不会给你任何的提示,而采用【basePackageClasses】会有错误提示。

3、自动装配——@Autowired

定义:由 Spring 自己发现对应的 Bean,自动完成装配工作的方式(根据类型查找

例子解析:

1.先在 Package【service】下创建一个 StudentService 接口:

package service;

public interface StudentService {
public void printStudentInfo();
}

PS:使用接口是 Spring 推荐的方式,这样可以更为灵活,可以将定义和实现分离

2.为上面的接口创建一个 StudentServiceImp 实现类:

@Component("studentService")//表示IoC把这个类扫描成一个bean实例(这里简写了,括号内等同于XML配置方式时的id)
public class StudentServiceImp implements StudentService { @Autowired//Spring自己发现bean并装配
private Student student = null; public void printStudentInfo() {
System.out.println("学生的 id 为:" + student.getName());
System.out.println("学生的 name 为:" + student.getName());
}
}

3.编写测试类:

// 第一步:修改 StudentConfig 类,告诉 Spring IoC 在哪里去扫描它:
package pojo; import org.springframework.context.annotation.ComponentScan; @ComponentScan(basePackages = {"pojo", "service"})
public class StudentConfig {
} // 或者也可以在 XML 文件中声明去哪里做扫描
<context:component-scan base-package="pojo" />
<context:component-scan base-package="service" /> // 第二步:编写测试类:
package test; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import pojo.StudentConfig;
import service.StudentService;
import service.StudentServiceImp; public class TestSpring { public static void main(String[] args) {
// 通过注解的方式初始化 Spring IoC 容器
ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);
StudentService studentService = context.getBean("studentService", StudentServiceImp.class);
studentService.printStudentInfo();
}
}

小结:

  @Autowired 注解表示在 Spring IoC 定位所有的 Bean 后,再根据类型寻找资源,然后将其注入。

  过程:定义 Bean ——》 初始化 Bean(扫描) ——》 根据属性需要从 Spring IoC 容器中搜寻满足要求的 Bean ——》 满足要求则注入

  问题: IoC 容器可能会寻找失败,此时会抛出异常(默认情况下,Spring IoC 容器会认为一定要找到对应的 Bean 来注入到这个字段,但有些时候并不是一定需要,比如日志)

  解决: 通过配置项 required 来改变,比如 @Autowired(required = false),该属性可控制IOC容器找不到Bean时不报错。

  PS:@Autowired 注解不仅仅能配置在属性之上,还允许方法配置,常见的 Bean 的 setter 方法也可以使用它来完成注入,总之一切需要 Spring IoC 去寻找 Bean 资源的地方都可以用到

Spring学习(六)bean装配详解之 【通过注解装配 Bean】【基础配置方式】的更多相关文章

  1. (转)spring学习之@ModelAttribute运用详解

    @ModelAttribute使用详解 1 @ModelAttribute注释方法 例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方法执行前被 ...

  2. spring学习之@ModelAttribute运用详解

    @ModelAttribute使用详解 1.@ModelAttribute注释方法     例子(1),(2),(3)类似,被@ModelAttribute注释的方法会在此controller每个方法 ...

  3. HAProxy详解(二):HAProxy基础配置与应用实例

    一.HAProxy基础配置与应用实例: 1.快速安装HAProxy集群软件: HAProxy的官网: https://www.haproxy.org/#down下载HAProxy的源码包. 安装: [ ...

  4. TCP/IP协议学习(六) 链路层详解

    学习知识很简单,但坚持不懈却又是如此的困难,即使一直对自己说"努力,不能停下"的我也慢慢懈怠了... 闲话不多说,本篇将讲述TCP/IP协议栈的链路层.在本系列第一篇我讲到,TCP ...

  5. [转载]springmvc学习之@ModelAttribute运用详解

    spring学习之@ModelAttribute运用详解 链接

  6. Spring学习(七)bean装配详解之 【通过注解装配 Bean】【自动装配的歧义解决】

    自动装配 1.歧义性 我们知道用@Autowired可以对bean进行注入(按照type注入),但如果有两个相同类型的bean在IOC容器中注册了,要怎么去区分对哪一个Bean进行注入呢? 如下情况, ...

  7. Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!

    点击下方链接回顾往期 不要再说不会Spring了!Spring第一天,学会进大厂! Spring第二天,你必须知道容器注册组件的几种方式!学废它吊打面试官! 今天讲解Spring中Bean的生命周期. ...

  8. J2EE学习篇之--Struts1详解

    今天来看一下Struts1的相关知识,其实Struts现在是出名的,每个Web开发者都会知道的,也是现在比较流行的框架,下面就来看一下我们为什么要用Struts框架呢? 摘要 1.建立在mvc这种好的 ...

  9. Spring Boot Actuator监控使用详解

    在企业级应用中,学习了如何进行SpringBoot应用的功能开发,以及如何写单元测试.集成测试等还是不够的.在实际的软件开发中还需要:应用程序的监控和管理.SpringBoot的Actuator模块实 ...

  10. HTTP协议 (六) 状态码详解

    HTTP协议 (六) 状态码详解 HTTP状态码,我都是现查现用. 我以前记得几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了.  如果 ...

随机推荐

  1. 问卷星的数据导入spss后变量乱码如何处理?

    一般是字符编码问题.打开一个空的SPSS数据集,选择[编辑]-[选项]-[常规]-[数据和语法的字符编码].修改下当前的编码系统,原来是第一种就换成第二种,原来是第二种就换成第一种,打开一个数据再看看 ...

  2. zero:如何找到SEO流量的突破口

    http://www.wocaoseo.com/thread-326-1-1.html 之前一篇文章已有提到过,SEO可以分为两个阶段: 一个阶段是了解点SEO知识,然后就到网站上去找页面,看哪些招式 ...

  3. Python字符串类型格式化之format方法

    python字符串格式化一般使用 format() 方法,用法如下: <模板字符串>.format(<逗号分割的参数>) 其中模板字符串中可以由一个或多个 {} 组成的 槽 , ...

  4. laravel Application实例化后两个方法

    laravel容器初始化registerBaseServiceProviders方法 上篇讲解了laravel容器的基本使用和原理,这篇继续Application构造方法中的registerBaseS ...

  5. Typescript | Vue3源码系列

    TypeScript 是开源的,TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript.编译出来的 JavaScript 可以运行在任何浏览器上.TypeS ...

  6. MySql密码的问题

    由于长时间没使用过MySql了,也由于之前没有做笔记的习惯,晚上因为MySQL的密码问题导致数据库长时间没连上.纠结了这么久还是决定记录下来,毕竟安装的东西多了,这年头到处都是密码,加上时间一长,很容 ...

  7. Python程序结构

    Python程序结构 分支结构 条件语句: if 判断: .....满足判断条件执行的代码块 else: .....不满足判断条件执行的代码块 if 判断1: .....满足判断条件1执行的代码块 e ...

  8. 浅谈HASH长度拓展攻击

    前言 最近在做CTF题的时候遇到这个考点,想起来自己之前在做实验吧的入门CTF题的时候遇到过这个点,当时觉得难如看天书一般,现在回头望去,仔细琢磨一番感觉也不是那么难,这里就写篇文章记录一下自己的学习 ...

  9. 图像通道、RGB与色彩体系

    通道(Channels) 图像的通道指的是什么?是不是灰度图的通道数为1,彩色图的通道为3 ? 图像通道,在RGB色彩模式下就是指那单独的红色.绿色.蓝色部分.也就是说,一幅完整的图像,是由红色绿色蓝 ...

  10. 使用java.io.RandomAccessFile更改文本文件的内容

    原文本内容: 2020-01-21 08:31:08.520 [main] INFO logbackCfg.App -秦时明月汉时关 2020-01-21 08:31:08.521 [main] ER ...