@@ -137,11 +137,11 @@ Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系
137137
138138如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比 Spring AOP 快很多。
139139
140- ## Spring bean
140+ ## Spring Bean
141141
142- ### 什么是 bean ?
142+ ### 什么是 Spring Bean ?
143143
144- 简单来说,bean 代指的就是那些被 IoC 容器所管理的对象。
144+ 简单来说,Bean 代指的就是那些被 IoC 容器所管理的对象。
145145
146146我们需要告诉 IoC 容器帮助我们管理哪些对象,这个是通过配置元数据来定义的。配置元数据可以是 XML 文件、注解或者 Java 配置类。
147147
@@ -158,50 +158,18 @@ Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系
158158
159159` org.springframework.beans ` 和 ` org.springframework.context ` 这两个包是 IoC 实现的基础,如果想要研究 IoC 相关的源码的话,可以去看看
160160
161- ### bean 的作用域有哪些 ?
161+ ### 将一个类声明为 Bean 的注解有哪些 ?
162162
163- Spring 中 Bean 的作用域通常有下面几种:
164-
165- - ** singleton** : 唯一 bean 实例,Spring 中的 bean 默认都是单例的,对单例设计模式的应用。
166- - ** prototype** : 每次请求都会创建一个新的 bean 实例。
167- - ** request** : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
168- - ** session** : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
169- - ** global-session** : 全局 session 作用域,仅仅在基于 portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
170-
171- ** 如何配置 bean 的作用域呢?**
172-
173- xml 方式:
174-
175- ``` xml
176- <bean id =" ..." class =" ..." scope =" singleton" ></bean >
177- ```
178-
179- 注解方式:
180-
181- ``` java
182- @Bean
183- @Scope (value = ConfigurableBeanFactory . SCOPE_PROTOTYPE )
184- public Person personPrototype() {
185- return new Person ();
186- }
187- ```
188-
189- ### 单例 bean 的线程安全问题了解吗?
190-
191- 大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。
192-
193- 常见的有两种解决办法:
194-
195- 1 . 在 bean 中尽量避免定义可变的成员变量。
196- 2 . 在类中定义一个 ` ThreadLocal ` 成员变量,将需要的可变成员变量保存在 ` ThreadLocal ` 中(推荐的一种方式)。
197-
198- 不过,大部分 bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, bean 是线程安全的。
163+ - ` @Component ` :通用的注解,可标注任意类为 ` Spring ` 组件。如果一个 Bean 不知道属于哪个层,可以使用` @Component ` 注解标注。
164+ - ` @Repository ` : 对应持久层即 Dao 层,主要用于数据库相关操作。
165+ - ` @Service ` : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
166+ - ` @Controller ` : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
199167
200168### @Component 和 @Bean 的区别是什么?
201169
202- 1 . ` @Component ` 注解作用于类,而` @Bean ` 注解作用于方法。
203- 2 . ` @Component ` 通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 ` @ComponentScan ` 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。` @Bean ` 注解通常是我们在标有该注解的方法中定义产生这个 bean,` @Bean ` 告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。
204- 3 . ` @Bean ` 注解比 ` @Component ` 注解的自定义性更强,而且很多地方我们只能通过 ` @Bean ` 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 ` Spring ` 容器时,则只能通过 ` @Bean ` 来实现。
170+ - ` @Component ` 注解作用于类,而` @Bean ` 注解作用于方法。
171+ - ` @Component ` 通常是通过类路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 ` @ComponentScan ` 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。` @Bean ` 注解通常是我们在标有该注解的方法中定义产生这个 bean,` @Bean ` 告诉了 Spring 这是某个类的实例,当我需要用它的时候还给我。
172+ - ` @Bean ` 注解比 ` @Component ` 注解的自定义性更强,而且很多地方我们只能通过 ` @Bean ` 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 ` Spring ` 容器时,则只能通过 ` @Bean ` 来实现。
205173
206174` @Bean ` 注解使用示例:
207175
@@ -240,16 +208,110 @@ public OneService getService(status) {
240208}
241209```
242210
243- ### 将一个类声明为 bean 的注解有哪些?
211+ ### @ Autowired 和 @ Resource 的区别是什么?
244212
245- 我们一般使用 ` @ Autowired` 注解自动装配 bean,要想把类标识成可用于 ` @Autowired ` 注解自动装配的 bean 的类,采用以下注解可实现:
213+ ` Autowired ` 属于 Spring 内置的注解,默认的注入方式为 ` byType ` (根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。
246214
247- - ` @Component ` :通用的注解,可标注任意类为 ` Spring ` 组件。如果一个 Bean 不知道属于哪个层,可以使用` @Component ` 注解标注。
248- - ` @Repository ` : 对应持久层即 Dao 层,主要用于数据库相关操作。
249- - ` @Service ` : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
250- - ` @Controller ` : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面。
215+ ** 这会有什么问题呢?** 当一个接口存在多个实现类的话,` byType ` 这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。
216+
217+ 这种情况下,注入方式会变为 ` byName ` (根据名称进行匹配),这个名称通常就是类名(首字母小写)。就比如说下面代码中的 ` smsService ` 就是我这里所说的名称,这样应该比较好理解了吧。
218+
219+ ``` java
220+ // smsService 就是我们上面所说的名称
221+ @Autowired
222+ private SmsService smsService;
223+ ```
224+
225+ 举个例子,` SmsService ` 接口有两个实现类: ` SmsServiceImpl1 ` 和 ` SmsServiceImpl2 ` ,且它们都已经被 Spring 容器所管理。
226+
227+ ``` java
228+ // 报错,byName 和 byType 都无法匹配到 bean
229+ @Autowired
230+ private SmsService smsService;
231+ // 正确注入 SmsServiceImpl1 对象对应的 bean
232+ @Autowired
233+ private SmsService smsServiceImpl1;
234+ // 正确注入 SmsServiceImpl1 对象对应的 bean
235+ // smsServiceImpl1 就是我们上面所说的名称
236+ @Autowired
237+ @Qualifier (value = " smsServiceImpl1" )
238+ private SmsService smsService;
239+ ```
240+
241+ 我们还是建议通过 ` @Qualifier ` 注解来显示指定名称而不是依赖变量的名称。
242+
243+ ` @Resource ` 属于 JDK 提供的注解,默认注入方式为 ` byName ` 。如果无法通过名称匹配到对应的实现类的话,注入方式会变为` byType ` 。
244+
245+ ` @Resource ` 有两个比较重要且日常开发常用的属性:` name ` (名称)、` type ` (类型)。
246+
247+ ``` java
248+ public @interface Resource {
249+ String name () default "";
250+ Class<?> type () default Object.class;
251+ }
252+ ```
253+
254+ 如果仅指定 ` name ` 属性则注入方式为` byName ` ,如果仅指定` type ` 属性则注入方式为` byType ` ,如果同时指定` name ` 和` type ` 属性(不建议这么做)则注入方式为` byType ` +` byName ` 。
255+
256+ ``` java
257+ // 报错,byName 和 byType 都无法匹配到 bean
258+ @Resource
259+ private SmsService smsService;
260+ // 正确注入 SmsServiceImpl1 对象对应的 bean
261+ @Autowired
262+ private SmsService smsServiceImpl1;
263+ // 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
264+ @Autowired
265+ @Resource (name = " smsServiceImpl1" )
266+ private SmsService smsService;
267+ ```
268+
269+ 简单总结一下:
270+
271+ - ` @Autowired ` 是 Spring 提供的注解,` @Resource ` 是 JDK 提供的注解。
272+ - ` Autowired ` 默认的注入方式为` byType ` (根据类型进行匹配),` @Resource ` 默认注入方式为 ` byName ` (根据名称进行匹配)。
273+ - 当一个类存在多个实现类的情况下,` @Autowired ` 和` @Resource ` 都需要通过名称进行匹配才能正确匹配到对应的 Bean。` Autowired ` 可以通过 ` @Qualifier ` 注解来显示指定名称,` @Resource ` 可以通过 ` name ` 属性来显示指定名称。
274+
275+ ### Bean 的作用域有哪些?
276+
277+ Spring 中 Bean 的作用域通常有下面几种:
278+
279+ - ** singleton** : 唯一 bean 实例,Spring 中的 bean 默认都是单例的,对单例设计模式的应用。
280+ - ** prototype** : 每次请求都会创建一个新的 bean 实例。
281+ - ** request** : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。
282+ - ** session** : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。
283+ - ** global-session** : 全局 session 作用域,仅仅在基于 portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。
284+
285+ ** 如何配置 bean 的作用域呢?**
286+
287+ xml 方式:
288+
289+ ``` xml
290+ <bean id =" ..." class =" ..." scope =" singleton" ></bean >
291+ ```
292+
293+ 注解方式:
294+
295+ ``` java
296+ @Bean
297+ @Scope (value = ConfigurableBeanFactory . SCOPE_PROTOTYPE )
298+ public Person personPrototype() {
299+ return new Person ();
300+ }
301+ ```
302+
303+ ### 单例 Bean 的线程安全问题了解吗?
304+
305+ 大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。
306+
307+ 常见的有两种解决办法:
308+
309+ 1 . 在 Bean 中尽量避免定义可变的成员变量。
310+ 2 . 在类中定义一个 ` ThreadLocal ` 成员变量,将需要的可变成员变量保存在 ` ThreadLocal ` 中(推荐的一种方式)。
311+
312+ 不过,大部分 Bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。
251313
252- ### bean 的生命周期 ?
314+ ### Bean 的生命周期了解么 ?
253315
254316> 下面的内容整理自:< https://yemengying.com/2016/07/14/spring-bean-life-cycle/ > ,除了这篇文章,再推荐一篇很不错的文章 :< https://www.cnblogs.com/zrtqsk/p/3735273.html > 。
255317
0 commit comments