当前位置:   article > 正文

简单存 Bean 对象 -- 五大类注解以及 Bean 方法注解_java bean注解

java bean注解

目录

一. 配置扫描路径

二. 简单存储 Bean 的五大类注解

1. @Controller 注解

2. @Service 注解

3. @Repository 注解

4. @Component 注解

5. @Configuration 注解

6. Bean 的命名规则

7. 为什么有这么多相同功能的类注解

8. 五大类注解之间有关系嘛?

1. @Controller 源码

2. @Service 源码

3. @Repository 源码

4. @Configuration 源码

5. @Component 源码

三. @Bean 方法注解

1. @Bean 方法注解的命名规则不同

对于第一个问题, 为什么此处是 User.class ?

对于第二个问题, 为什么此处是 User 返回值 ?

对于第三个问题, 为什么这里任然报错 ?

2. @Bean 方法注解需要搭配类注解使用

四. 五大类注解和 @Bean 方法注解多次注入

1. 五大类注解多次注入

1. 修改其中一个类中 @Controller的 value 属性

2. @Bean 方法多次注入


一. 配置扫描路径

前面创建 Spring 项目和简单使用一文中说到(如何创建一个 Spring 项目并简单使用), 在获取 Spring 的上下文对象时, 是先去 配置文件中读取, 获得 Spring 容器. 因此, 在使用更简单的存 Bean 对象的注解时, 我们也需要进行配置文件

  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:content="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. <!-- 配置扫描路径, 指定要扫描那个路径底下的类注解, 不在该包底下或者在该包底下不加五大类注解都不能读取 -->
  7. <!-- 在component-scan 下的子包下加了五大类注解一样可以加入到bean中 -->
  8. <content:component-scan base-package="demo1.java"></content:component-scan>
  9. </beans>

想要用注解的方式将 Bean 对象注册到 Spring 容器中 , 就需要配置 content: component-scan base-package="具体包路径", 只有配置包路径地下的所有类, 添加了注解才能被正确识别到注册到 Spring 中

二. 简单存储 Bean 的五大类注解

1. @Controller 注解

同样的, 要进行注册到 Spring 容器中, 需要先创建 Bean 对象(普通 Java 对象)

创建好了对象以后, 采用三步走获取 Bean 对象并使用

 

调用方法成功, 表示成功获取指定 Bean 对象

  @controller 表示的是业务逻辑层

2. @Service 注解

同上面一样, 创建 Bean 对象并添加注解进行获取使用

 调用方法成功

3. @Repository 注解

 调用方法成功

4. @Component 注解

调用方法成功

 @Component 组件存储

5. @Configuration 注解

调用方法成功

 6. Bean 的命名规则

上面的五大类注解中, 都会发现一个问题: 那就是这里的获取 Bean 对象时, 使用的不在是 spring-config.xml 里的指定 Bean 标签的 id 和类 类型的组合获取 Bean 对象, 哪该如何获取类注解下注入的 Bean 对象呢?

下面看一组示例

 调用方法验证

此时我们发现, 和上面五大类注解讲解的时候是一样的获取方法, 但是现在却报错了这是为什么? 仔细看不难发现, 之前的五大类讲解时, 都是类名首字母大写, 而这里是类名的首字母和第二个字母都大写, 因此, 此处我们就要去看看 Bean 的命名规则到底是如何讲解的了

  1. public static String decapitalize(String name) {
  2. if (name == null || name.length() == 0) {
  3. return name;
  4. }
  5. if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
  6. Character.isUpperCase(name.charAt(0))){
  7. return name;
  8. }
  9. char chars[] = name.toCharArray();
  10. chars[0] = Character.toLowerCase(chars[0]);
  11. return new String(chars);
  12. }

以上为 BeanName 的命名源码, 从上面源码可以看出, 当 首字母和第二个字母都大写的时候, 直接放回当前类名

 7. 为什么有这么多相同功能的类注解

细心的可以发现, 上面五大类注解都干了同一件事, 那就是将 Bean 对象注入到 Spring 容器中, 那为什么还需要搞这么多个类注解呢? 是否有这个疑问?

我们知道, 在开发中, 会需要大量注解不同的对象以供使用, 那么这些对象的用途都是什么呢?  既然它叫做类注解, 说明他是在类上作用的, 同时他最大的作用还有注解功能! 让程序员可以一眼就看出来这个类的用途, 高效开发!

8. 五大类注解之间有关系嘛?

既然功能都是差不多, 那么他们之间有什么关系嘛?

就这个问题, 去看他们的源码

1. @Controller 源码

2. @Service 源码

3. @Repository 源码

4. @Configuration 源码

5. @Component 源码

通过观察上述源码, 发现五大类注解中, 都包含有 @Target @Retention @Documented 注解 ,

同时 除了 @Component 注解外, 其余四个注解都包含了 @Component 注解 

因此, 我们可以知道, 其他四个注解都是 @Component 注解的子类

三. @Bean 方法注解

前面学的类注解, 是添加在类上的, 而 Bean 方法注解则是添加到方法上的, 通常 @Bean注解是需要有返回值的, 表明通过 Bean 方法注解把某个返回的对象注入到 Spring 容器中. 这样就可以将自定义的类型在需要的时候注入到 Spring 容器中

此处创建一个 User 类, 里面包括一些 username, Id, age 等字段表明 User 的信息, 下面将这些信息注入到 Spring 中

接下来正常去获取 Spring 容器并获得Bean对象使用

明明和之前五大类注解的获取方式一样, bean命名一样, 却获取不到正确 Bean 对象这是为什么? 原因一共有以下两点:

1. @Bean 方法注解的命名规则不同

在@Bean 方法注解中, 不在是使用五大类注解的 Bean 命名规则: 首字母大写则命名时首字母小写; 首字母和第二个字母都大写, 则按原类名命名

@Bean 的命名规则默认为@Bean 方法注解加到那个方法上, bean的名称就是 方法该名称, 例如此处 @Bean 加到了 user1 方法上, 因此此处应该使用 user1 名

对于第一个问题, 为什么此处是 User.class ?

由于@Bean 注解的作用是将类中的某个方法的返回值注入到 Spring 容器中, 此处 bean 的命名用的是 user1 的方法名称, 返回值 是 User 类型, 因此此处是 User.class 

对于第二个问题, 为什么此处是 User 返回值 ?

和上面一样, 用了 User.class 解析, 返回的必须是 User 类型接收

对于第三个问题, 为什么这里任然报错 ?

这就涉及到 @Bean 方法注解的第二个注意项, 详细看下文

2. @Bean 方法注解需要搭配类注解使用

调用方法验证

现在就正确拿到了 @Bean 方法注解 把 User 类型返回注入到 Spring 容器中的 Bean 对象了

那么, 只有我上面用的@Component 类注解可以搭配嘛? 其实不然, 五大类中的任意一个都可以.

那么为什么又需要搭配五大类注解使用呢 ?

大致原因如下: 出于性能方面的考虑, 加了五大类注解以后就只能放在扫描包路径底下, 不用去检测其他地方的 @Bean 注解. 

哪又有人会问了, 为什么 @Bean 方法注解不能像类注解一样直接注入到 Spring 容器中呢? 

正如上面所说, 由于已经规定了五大类注解在扫描包底下才起作用, 减少扫描开销, 因此 @Bean 便引入搭配类注解使用, 来提高性能

四. 五大类注解和 @Bean 方法注解多次注入

上面已经给 五大类注解和 @bean 方法注解说明白了, 那么现在有一个问题 如果多次注入会怎么样呢? 下面就来讨论一下多次注入的情况

1. 五大类注解多次注入

有没有这样的疑问, 在扫描包路径底下, 创建两个不同的包, 不同的包下创建相同类, 并注入到 Spring 中会怎么样呢?

这两个ControllerStudent 都是位于 spring-config.xml里的扫描包路径底下的, 但是两个类在不同包底下, 哪现在该如何去获取呢?

去尝试获取 demo1.demo2 包路径底下 Bean 对象并使用时发现, 无法获取唯一的指定 Bean 对象, 那这个时候该怎么去获取呢?

1.修改其中一个类中 @Controller的 value 属性

比如现在, 我给 demo1.demo2.test 包路径底下的 ControllerStudent 设置value 属性, 起一个新的Bean 名称

 

再去调用运行

 这个时候发现, demo1. demo2 底下的 ControllerStudent 可以正确获取了, 同时还可以用新取的name去获取 demo1.demo2.test 底下的 COntrollerStudent

 2. @Bean 方法多次注入

同样的, 在指定的扫描包路径底下有两个不同包下的相同类通过 @Bean 注入到 Spring 中

获取Bean对象并使用

可以看到并没有报错, 但是为什么是输出的 demo1.demo2.test 包下的 getUserName 呢?

原因在于, 如果在扫描路径下, 多次用 @Bean 注入返回相同对象, 则会根据包级覆盖, 包越大下的对象越先注入, 会被后面的覆盖

哪要怎样才能获取指定想要的呢 ?

和上面一样. 采取给 @Bean 方法注解添加 Value 属性

 

调用验证

这样就可以正确获取想要的了, 但是在项目中, 建议大家还是尽量不要多次注入相同对象或者频繁创建 Spring 容器以及销毁, 避免带来非预期的调用结果, 影响程序 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号