简单存 Bean 对象 -- 五大类注解以及 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 对象的注解时, 我们也需要进行配置文件

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--  配置扫描路径, 指定要扫描那个路径底下的类注解, 不在该包底下或者在该包底下不加五大类注解都不能读取  -->
<!--  在component-scan 下的子包下加了五大类注解一样可以加入到bean中  -->
    <content:component-scan base-package="demo1.java"></content:component-scan>
</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 的命名规则到底是如何讲解的了

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        char chars[] = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

以上为 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 容器以及销毁, 避免带来非预期的调用结果, 影响程序 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值