赞
踩
目录
1. 修改其中一个类中 @Controller的 value 属性
前面创建 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 中
同样的, 要进行注册到 Spring 容器中, 需要先创建 Bean 对象(普通 Java 对象)
创建好了对象以后, 采用三步走获取 Bean 对象并使用
调用方法成功, 表示成功获取指定 Bean 对象
@controller 表示的是业务逻辑层
同上面一样, 创建 Bean 对象并添加注解进行获取使用
调用方法成功
调用方法成功
调用方法成功
@Component 组件存储
调用方法成功
上面的五大类注解中, 都会发现一个问题: 那就是这里的获取 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 的命名源码, 从上面源码可以看出, 当 首字母和第二个字母都大写的时候, 直接放回当前类名
细心的可以发现, 上面五大类注解都干了同一件事, 那就是将 Bean 对象注入到 Spring 容器中, 那为什么还需要搞这么多个类注解呢? 是否有这个疑问?
我们知道, 在开发中, 会需要大量注解不同的对象以供使用, 那么这些对象的用途都是什么呢? 既然它叫做类注解, 说明他是在类上作用的, 同时他最大的作用还有注解功能! 让程序员可以一眼就看出来这个类的用途, 高效开发!
既然功能都是差不多, 那么他们之间有什么关系嘛?
就这个问题, 去看他们的源码
通过观察上述源码, 发现五大类注解中, 都包含有 @Target @Retention @Documented 注解 ,
同时 除了 @Component 注解外, 其余四个注解都包含了 @Component 注解
因此, 我们可以知道, 其他四个注解都是 @Component 注解的子类
前面学的类注解, 是添加在类上的, 而 Bean 方法注解则是添加到方法上的, 通常 @Bean注解是需要有返回值的, 表明通过 Bean 方法注解把某个返回的对象注入到 Spring 容器中. 这样就可以将自定义的类型在需要的时候注入到 Spring 容器中
此处创建一个 User 类, 里面包括一些 username, Id, age 等字段表明 User 的信息, 下面将这些信息注入到 Spring 中
接下来正常去获取 Spring 容器并获得Bean对象使用
明明和之前五大类注解的获取方式一样, bean命名一样, 却获取不到正确 Bean 对象这是为什么? 原因一共有以下两点:
在@Bean 方法注解中, 不在是使用五大类注解的 Bean 命名规则: 首字母大写则命名时首字母小写; 首字母和第二个字母都大写, 则按原类名命名
@Bean 的命名规则默认为@Bean 方法注解加到那个方法上, bean的名称就是 方法该名称, 例如此处 @Bean 加到了 user1 方法上, 因此此处应该使用 user1 名
由于@Bean 注解的作用是将类中的某个方法的返回值注入到 Spring 容器中, 此处 bean 的命名用的是 user1 的方法名称, 返回值 是 User 类型, 因此此处是 User.class
和上面一样, 用了 User.class 解析, 返回的必须是 User 类型接收
这就涉及到 @Bean 方法注解的第二个注意项, 详细看下文
调用方法验证
现在就正确拿到了 @Bean 方法注解 把 User 类型返回注入到 Spring 容器中的 Bean 对象了
那么, 只有我上面用的@Component 类注解可以搭配嘛? 其实不然, 五大类中的任意一个都可以.
那么为什么又需要搭配五大类注解使用呢 ?
大致原因如下: 出于性能方面的考虑, 加了五大类注解以后就只能放在扫描包路径底下, 不用去检测其他地方的 @Bean 注解.
哪又有人会问了, 为什么 @Bean 方法注解不能像类注解一样直接注入到 Spring 容器中呢?
正如上面所说, 由于已经规定了五大类注解在扫描包底下才起作用, 减少扫描开销, 因此 @Bean 便引入搭配类注解使用, 来提高性能
上面已经给 五大类注解和 @bean 方法注解说明白了, 那么现在有一个问题 如果多次注入会怎么样呢? 下面就来讨论一下多次注入的情况
有没有这样的疑问, 在扫描包路径底下, 创建两个不同的包, 不同的包下创建相同类, 并注入到 Spring 中会怎么样呢?
这两个ControllerStudent 都是位于 spring-config.xml里的扫描包路径底下的, 但是两个类在不同包底下, 哪现在该如何去获取呢?
去尝试获取 demo1.demo2 包路径底下 Bean 对象并使用时发现, 无法获取唯一的指定 Bean 对象, 那这个时候该怎么去获取呢?
比如现在, 我给 demo1.demo2.test 包路径底下的 ControllerStudent 设置value 属性, 起一个新的Bean 名称
再去调用运行
这个时候发现, demo1. demo2 底下的 ControllerStudent 可以正确获取了, 同时还可以用新取的name去获取 demo1.demo2.test 底下的 COntrollerStudent
同样的, 在指定的扫描包路径底下有两个不同包下的相同类通过 @Bean 注入到 Spring 中
获取Bean对象并使用
可以看到并没有报错, 但是为什么是输出的 demo1.demo2.test 包下的 getUserName 呢?
原因在于, 如果在扫描路径下, 多次用 @Bean 注入返回相同对象, 则会根据包级覆盖, 包越大下的对象越先注入, 会被后面的覆盖
哪要怎样才能获取指定想要的呢 ?
和上面一样. 采取给 @Bean 方法注解添加 Value 属性
调用验证
这样就可以正确获取想要的了, 但是在项目中, 建议大家还是尽量不要多次注入相同对象或者频繁创建 Spring 容器以及销毁, 避免带来非预期的调用结果, 影响程序
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。