Spring学习(三)(类注解和方法注解)

目录

1. 存储Bean对象

1.1 配置扫描路径

1.2 添加注解存储Bean对象

1.2.1 @Controller(控制器存储)

 1.2.2 @Service(服务存储)

1.3 这么多注解???为什么??

 1.3.1 类注解时间的关系

1.4 方法注解@Bean

1.4.1 @Bean重命名

1.4.2 @Bean存储多个相同对象

2.获取Bean对象(对象装配)

2.1 属性注入

2.2 Setter注入

2.3 构造方法注入(Spring官方推荐)

2.4 @Resource注解


1. 存储Bean对象

通过再配置文件中添加bean注册内容的方式来存储bean感觉是一个十分不方便的操作。想要通过更加简单的操作来实现对bean的注册该怎么办呢?Spring为使用者还提供了通过注解的方式来注册bena。这种方式也是主流的方式,工作当中也大多是通过这种方式来注册bean的,因为十分的方便,而且关联到java的标准分层。

1.1 配置扫描路径

配置扫描路径是什么意思呢??难道不是直接在需要的地方加上注解就可以了吗??

Spring作为一个成熟的框架,肯定是要追求效率的,如果是直接加上注解就可以注册的话,就必须扫描所有的代码遍历去检查有没有注册的需求。这样逻辑工作的话,效率肯定是十分低下的,为了提高效率,Spring决定只扫描在配置在base-package包以及其子包。如果不在base-package包下的地方即使加上了注解也是没有办法注册bean的,在使用的时候就会报错。只有被配置的包下的所有类,并且添加了注解才能被正确的识别并保存到 Spring 中。

怎么配置扫描路径?只需要在spring-config.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:content="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans htt
p://www.springframework.org/schema/beans/spring-beans.xsd http://www.spring
framework.org/schema/context https://www.springframework.org/schema/contex
t/spring-context.xsd"><content:component-scan base-package="com.xxx.yyy"></content:compon
ent-scan>
</beans>

其中

添加完扫描路径以后,Spring就会在这个包下面扫面有哪些添加了注解然后将其存储到Spring中。

1.2 添加注解存储Bean对象

Spring提供了两种类型的注解来帮助使用者将对象存储到Spring当中。

  • 1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
  • 2. ⽅法注解:@Bean。

 下面先来介绍他们是怎么使用的,然后再去介绍他们的使用场景。

1.2.1 @Controller(控制器存储)

首先它是一个类注解,使用的时候就是在想要存储的类上加上这个注解。使用@Controller存储bean的代码如下所示:

@Controller
public class UserController {public void sayHi(String name){System.out.println("Hi I am " + name);}
}

读取使用起来还是一样的:

public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到 beanUserController userController = (UserController) context.getBean("userController");// 3.调⽤ bean ⽅法userController.sayHi("Zhangsan");}
}

其实现在有一个小问题,我们使用注解的时候并没有指定id啊,这样我们在读取的时候是怎么样知道他的id并且是获取的呢?根据上面的使用情况来看即使将注解的类名的首字母改成小写就是存储的id,那么到底是不是这样的?

答案其实不是这样的,这需要搞清楚类注解的bean命名规则才能得到答案。我们可以看一下Spring的源码中对于BeanName的实现到底是什么情况?在 Idea 中使⽤搜索关键字“beanName”可以看到以下内容:

 

 看完源代码之后就能十分确定我们在使用的时候怎么确定ID了,分为两种情况:

  • 1.类名首字母和第二个字母都是大写的情况下,bean的名字就是类名;
  • 2.其他情况下就是将首字母改为小写作为bean的名字。

 1.2.2 @Service(服务存储)

使⽤ @Service 存储 bean 的代码如下所示,和前面的controller的使用方法一致。

@Service
public class UserService {public void sayHi(String name) {System.out.println("Hi," + name);}}
public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到 beanUserController userController = (UserController) context.getBean("userService");// 3.调⽤ bean ⽅法userController.sayHi("Zhangsan");}
}

剩下的集中情况不再去逐个演示,使用起来的方式都是大同小异,在类上加上对应的注解就可以了。用法并不是重点,重点是为什么提供这么多的注解??而且他们的使用方法都是一致的,这是为什么??

1.3 这么多注解???为什么??

那么为什么需要怎么多的类注解也是相同的原因,就是让程序员看到类注解之后,就能直接了解当前类 的⽤途,⽐如:

  • @Controller:表示的是业务逻辑层;
  • @Servie:服务层;
  • @Repository:持久层;
  • @Configuration:配置层。

这样就涉及到程序的工程分层,调用的流程大致如下:

 1.3.1 类注解时间的关系

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:

其实这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“⼦类”

1.4 方法注解@Bean

通过学习发现类注解是加在类上面的,想必方法注解就是加在某个方法上面了。另外要注意的是,这个方法必须要有一个返回值,如果没有返回值的话,Spring存什么呢?所以必须是要有一个返回值的,然后将这个返回值存入到spring中。并且存入的时候只能存一个无参方法的返回值。

先来看一下直接在方法上加上Bean注解是否能够成功使用?

public class StudentBeans {@Bean // 使用Bean注解讲函数的返回值也就是Student对象存储到spring中public Student stu1(){Student student = new Student("tom");student.setAge(18);student.setPassword("123456");return student;}
}public class App {public static void main(String[] args) {// 1.得到 spring 上下⽂ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");// 2.得到 beanStudent stu1 = context.getBean("student", Student.class);// 3.调⽤ bean ⽅法System.out.println(stu1.getName());}}

 

 运行时候发现报错,No bean named 'student' available,也就是我们spring中没有student。实际上造成上面报错的原因是代码中包含两处错误:

  • 1.Bean方法注解的命名规则相较于类注解已经发生了变化,Bean方法注解存入的id就是方法名,和类名没有任何的关系。比如 public Student stu1()中存入的id就是stu1。
  • 2. Bean注解必须搭配五大类注解使用才可以生效,否则也会报错。

 加入类注解,根据bean命名规则修改代码后:

 

 运行代码,观察是否能够成功获取到stu对象:

1.4.1 @Bean重命名

@Bean(name = {"student","stu"})

使用上面的代码可以给@Bean存入的对象重命名,而且可以起多个名字。name可以使用value替换。但是当@Bean重命名以后原来的默认的id就无法再获取到了。也就是通过

Student stu1 = context.getBean("stu1" , Student.class);无法在获取到存入的对象,只能通过重命名以后的id来获取到。在使用的时候要注意这个地方

1.4.2 @Bean存储多个相同对象

 当使用@Bean注解存储多个相同对象的时候可以使用重命名来加以区分:

@Component
public class StudentBeans {@Bean(name = {"student","stu"}) // 使用Bean注解讲函数的返回值也就是Student对象存储到spring中public Student stu1(){Student student = new Student("tom");student.setAge(18);student.setPassword("123456");return student;}@Bean(name = {"student1","stu1"}) // 使用Bean注解讲函数的返回值也就是Student对象存储到spring中public Student stu(){Student student = new Student("jack");student.setAge(18);student.setPassword("123456");return student;}
}

如果现在在两个不同的类中,分别存在一个方法名和返回值都一样的方法并且都是用了@Bean注解,会不会报错??

 

 答案是不会报错,但是每次运行的结果都是相同的结果,并不是随机的(我这里每次都是jordan)

 

这里可以通过@Oeder()来控制注入的顺序,值越小,越先注入,然后就会被后者注入的覆盖掉。

 

2.获取Bean对象(对象装配)

2.1 属性注入

缺点:

  • 无法注入final修饰的变量;

 

  • 只能适用于IoC容器,兼容性不好;
  • 此恶法简单,更容易违反单一设计原则;

优点:

  • 使用十分简单;

2.2 Setter注入

优点:更符合单一设计原则,每次都只传递一个对象;

缺点:

  • 不可以注入一个final修饰的变量;

 

  • 使用Setter注入的对象可以被修改 ,因为使用的载体就是一个setter方法,setter方法可以被多次调用;

2.3 构造方法注入(Spring官方推荐)

当当前类中只有一个构造方法的时候,@Autowired注解可以省略不写!

优点:

  • 1.可注入final修饰的变量;

为什么构造方法可以注入final修饰的不可变对象呢??因为java中被final修饰的对象,必须满足:final修饰的对象直接被赋值  或者  final修饰的对象在构造方法中被赋值

  • 2.注入的对象不会被修改,因为构造方法只能执行一次;
  • 3 .构造方法注入可以保证注入对象被完全初始化;
  • 4.构造方法的兼容性更好,即使脱离了IoC容器中也可以使用。

缺点:

  • 可能会违反单一设计原则(使用者可控,一般来说不会违反);

2.4 @Resource注解

@Resource在属性注入和Setter注入场景下可以替换@Autowired,但是在构造方法注入场景下只能使用@Autowired注解;

@Resource支持更多的参数设置:(当同一个类型的类被注入多个在spring当中的时候,使用@Autowired可能会解决不了命名冲突的问题,这时候就只能使用@Resource来给注入的bean重命名)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/9266.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

J2EE自定义mvc【框架配置及功能】

目录 一、配置步骤 二、配置框架前三步 导入相应的jar 导入相应的Class 导入xml文件 三、优化基本操作&#xff08;增删改&#xff09; 1、基础优化 编写实体类 编写BookDao类 优化BookDao JUnit测试 2、后台优化 3、前端优化 一、配置步骤 将框架打成jar包&…

【Hello mysql】 数据库库操作

Mysql专栏&#xff1a;Mysql 本篇博客简介&#xff1a;介绍数据库的库操作 库的操作 创建数据库创建数据库案例字符集和校验规则查看系统默认字符集和校验规则查看数据库支持的字符集和校验规则 校验规则对于数据库的影响操纵数据库查看数据库显示创建语句修改数据库数据库删除…

集成运放电路计算(全)

自记&#xff1a; 常用运放电路计算与分析 1、运放的符号表示 2、集成运算放大器的技术指标 (1) 开环差模电压放大倍数(开环增益)大 Ao(Ad)Vo/(V-V-)107-1012倍; (2) 共模抑制比高 KCMRR100db以上; (3) 输入电阻大 ri>1MW, 有的可达100MW以上; (4) 输出电阻小 ro 几W-几十…

Leetcode-每日一题【234.回文链表】

题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1]输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;head…

日历与时钟

目录 公历 黑色星期五 生物韵律 公历 在公历中&#xff0c;当年份为4的整数倍&#xff0c;但不是100的整数倍时&#xff0c;会出现闰年的现象。 y40 mod(y,4) 0 && mod(y,100)||mod(y,400)0 输出当时的年、月、日、时、分、秒 f%6d %6d %6d %6d %6d %9.3f\n cclock …

面向对象五大基本原则

面向对象五大基本原则 更多精彩 先案例后讲解&#xff0c;这里是代码教父&#xff0c;今天讲解面向对象的五大基本原则&#xff1a; 单一职责原则&#xff08;The Single Responsibility Principle&#xff09;开闭原则&#xff08;The Open-Closed Principle&#xff09;里氏…

深度学习-第T10周——数据增强

深度学习-第T10周——数据增强 深度学习-第T10周——数据增强一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目 四、数据预处理1、 加载数据1.1、设置图片格式1.2、划分训练集1.3、划分验证集1.4、查看标签1.5、再次检查数据1.6、配置数据集 2、数据可视化 五、数…

通过ioctl函数选择不同硬件的控制,LED 蜂鸣器 马达 风扇

通过ioctl函数选择不同硬件的控制&#xff0c;LED 蜂鸣器 马达 风扇 实验现象 head.h #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{volatile unsigned int MODER; // 0x00volatile unsigned int OTYPER; // 0x04volatile unsigned int OSPEEDR; // 0x08volati…

Unity Editor扩展 实现一个Excel读表窗口

设计 Unity Editor窗口类 public class ExcelEditorWindow : EditorWindow {[MenuItem( "Frameworks/读表配置界面", false, 10 )]private static void Open(){Rect wr new Rect( 0, 0, 500, 500 );ExcelEditorWindow window ( ExcelEditorWindow ) EditorWindow.…

React hooks文档笔记(二) 添加交互性

添加交互性 1. 事件传播1.1 停止传播1.2 阻止默认事件 2. [Hook] useState 状态3. 渲染和提交3.1 触发渲染3.2 React渲染组件3.3 提交对 DOM 的更改3.4 浏览器绘制 4. 渲染快照状态队列例子 5. 更新state中的对象 1. 事件传播 js的事件流&#xff1a; 事件捕获&#xff1a;从…

【DBA课程-笔记】MongoDB入门到云上开发

课程目的&#xff1a;成为专业MongoDB的DBA nosql第一&#xff1a;MongoDB 一、讲师&#xff1a; 二、课程目录 第1章&#xff1a;MongoDB数据库入门 第2章&#xff1a;MongoDB数据数据查询与分析 第3章&#xff1a;MongoDB数据库核心知识 第4章&#xff1a;MongoDB数据库管…

MySQL索引

文章目录 MySQL索引1 索引1.1 索引的概念1.2 索引的作用1.3 创建索引的原则依据 2 索引的分类和创建2.1 普通索引2.1.1 直接创建索引2.1.2 修改表方式创建2.1.3 创建表的时候指定索引 2.2 唯一索引2.2.1 直接创建唯一索引2.2.2 修改表方式创建唯一索引2.2.3 创建表的时候指定唯…