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