目录
在前面的文章中,我们介绍了通过 @Autowired 注解的方式来获取到Spring容器中的Bean对象,实际上,还有另一个注解:@Resource,它的功能也是差不多的,也可以从 Spring容器中获取到Bean对象,但也是存在一定的差别的。
问题分析:当在 Spring 中存放多个同一类型 Bean 对象的时候,使用 @Autowired 去获取 Bean对象会出错。
@Component
public class UserBeans {
@Bean
public User user1(){
User user = new User();
user.setAge(20);
user.setId(1);
user.setName("张三");
return user;
}
@Bean
public User user2(){
User user = new User();
user.setAge(22);
user.setId(11);
user.setName("李四");
return user;
}
}
@Controller
public class UserController2 {
@Autowired
private User user;
public void sayHi(){
System.out.println("do UserController2");
System.out.println(user.getName());
}
}
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController2 userController2 = context.getBean("userController2",UserController2.class);
userController2.sayHi();
}
}
此时执行是会报错的,因为 @Autowired 注解先通过类型去查找,得到了 user1 和 user2 两个 Bean对象,但是根据 user 名称来去查找的话,是没有找到对应的 Bean 对象的,因此会报错。(查找 Bean 对象的默认名称为 添加 @Autowired 注解的对应属性名称,也就是上述第二段代码的private User user)
解决办法1:修改 @Autowired 注解的对应属性名称
@Controller
public class UserController2 {
@Autowired
private User user1;
public void sayHi(){
System.out.println("do UserController2");
System.out.println(user1.getName());
}
}
此时运行代码就会获取到对应的 Bean对象,也就是存储的 user1 对象。
解决办法2:配合使⽤ @Qualifier 注解定义名称
@Qualifier(value = "Bean对象的名称")
@Controller
public class UserController2 {
@Autowired
@Qualifier(value="user1")
private User user;
public void sayHi(){
System.out.println("do UserController2");
System.out.println(user.getName());
}
}
也可以得到预期的结果。
解决办法3:使⽤ @Resource(name="Bean对象名称") 定义
@Controller
public class UserController2 {
@Resource(name="user1")
private User user;
public void sayHi(){
System.out.println("do UserController2");
System.out.println(user.getName());
}
}
同样是可以得到预期结果的。
限定程序中变量的可⽤范围叫做作用域,或者说在源代码中定义变量的某个区域就叫做作用域。而 Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种行为模式。
singleton 表示的是单例作用域,类似于之前讲过的单例模式。这也是默认情况下的行为模式。在该作用域下的 Bean 在 IoC容器中只存在一个实例,获取到的 Bean 以及对 Bean 进行修改,都是针对同一个 Bean 对象。
代码演示:
1. 往 Spring 容器中注入一个 User 对象
@Component
public class UserBeans {
@Bean
public User user(){
User user = new User();
user.setId(1);
user.setName("张三");
return user;
}
}
2. 通过@Autowired获取到Bean对象,并对其进行修改
@Controller
public class UserController {
@Autowired
private User user;
public void printUser(){
System.out.println(user);
// 修改 User
User myUser = user; // 给引用对象赋值,其实就是共享对象!!!这两个变量指向了同一个地址
myUser.setName("李四");
System.out.println("myUser -> " + myUser);
System.out.println("User -> " + user);
}
}
3. 再新建一个类,通过 @Autowired 获取到Bean对象
@Controller
public class UserController2 {
@Resource
private User user;
public void printUser2(){
System.out.println("user -> " + user);
// Bean 作用域 -> 默认是单例模式 = 此 Bean 在整个框架(Spring 容器)中只有一份
}
}
4. 最后输出观察结果
public class App {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean("userController",UserController.class);
userController.printUser();
UserController2 userController2 = context.getBean("userController2",UserController2.class);
userController2.printUser2();
}
}
因此也可以得出结论:singleton 单例作用域,他们使用的 Bean 都是 Spring 容器中的同一个对象。这个 Bean 在整个 Spring 中只有一份,是全局共享的,当其他人修改了这个值之后,那么另一个人读到的就是被修改后的值了。
在原型模式下,每次对该作用域下的 Bean 的请求都会创建新的实例,也就是说每次获取 Bean 对象和修改 Bean 对象都是针对新的 Bean 对象实例而言的。
需要添加注解 @Scope("prototype") 或者@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
代码演示:
@Component
public class UserBeans {
@Bean
@Scope("prototype")
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public User user(){
User user = new User();
user.setId(1);
user.setName("张三");
return user;
}
}
再次运行得到结果:
可以看出,在第二次通过 @Autowired 获取到 Bean 对象的时候,得到的是一个新的实例对象了。
每次 http 请求会创建新的 Bean 实例。适用于⼀次 http 的请求和响应的共享 Bean 的情况。
限定SpringMVC中使⽤。
在⼀个http session中,定义⼀个 Bean 实例。每次 Session 会话共享一个 Bean 对象。限定SpringMVC中使⽤。
给 Bean 对象分配内存空间。
此处要注意:初始化不等于实例化!!!
类的初始化是完成程序前的准备工作,在这个阶段,静态的会被执行,同时会开辟一块存储空间用来存放静态的数据,给对象的属性值赋值,调用初始化方法,初始化只在类加载的时候执行一次,也可以理解为给对象赋值的过程。
类的实例化,是指创建一个对象的过程,这个过程会在堆中开辟内存,将一些非静态的方法,变量存放在里面,属性值是默认值,在程序执行的过程中,可以创建多个对象,即多次实例化,每次实例化都会开辟一块新的内存。
看需求,有的 Bean 对象需要被注入属性,这个属性也会是已经在 Spring 容器中的 Bean,如果该属性还不存在于 Spring 中,那么会先去将该属性 Bean 存储到 Spring 中。
实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接⼝⽅法;
有两种方式,第一种是通过注解 @PostConstruct ,依赖注⼊操作之后执行注解修饰的方法;第二种是通过 xml 的方式,执行自己指定的 init-method ⽅法。如果两者都存在,那么先执行注解的初始化方法。
通过 getBean() 方法来获取容器中的 Bean 对象并使用。
销毁容器的各种⽅法,如 @PreDestroy、DisposableBean 接⼝⽅法、destroy-method(XML的方式)。
public class App {
public static void main(String[] args) {
// 此时要使用 ApplicationContext 的子类,因为它本身是没有销毁方法的
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
BeanComponent beanComponent = context.getBean("beanComponent",BeanComponent.class);
beanComponent.sayHi();
context.close();
}
}
public class BeanComponent implements BeanNameAware {
@Override
public void setBeanName(String s) {
System.out.println("执行了通知 BeanName -> " + s);
}
/**
* xml 方式的初始化方法
*/
public void myInit(){
System.out.println("XML 方式初始化");
}
@PostConstruct
public void doPostConstruct(){
System.out.println("注解的初始化方法");
}
public void sayHi(){
System.out.println("执行 sayHi()");
}
// 销毁的方法,销毁的时候执行的一个方法
@PreDestroy
public void doPreDestroy(){
System.out.println("do PreDestroy");
}
}
文章浏览阅读122次。还是A+BTime Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24568Accepted Submission(s): 11729Problem Description读入两个小于10000的正整数A和B,计算A+B。...
文章浏览阅读419次。HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息。FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。NONE:不记录任何日志信息,这是默认值。配置Feign日志有两种方式;方式二:java代码实现。注解中声明则代表某服务。方式一:配置文件方式。_feign 日志设置
文章浏览阅读155次。将容器管理的持久性 Bean 用于面向服务的体系结构本文将介绍如何使用 IBM WebSphere Process Server 对容器管理的持久性 (CMP) Bean的连接和持久性逻辑加以控制,使其可以存储在非关系数据库..._javax.ejb.objectnotfoundexception: no such entity!
文章浏览阅读1.5k次。基础java练习题一、递归实现跳台阶从第一级跳到第n级,有多少种跳法一次可跳一级,也可跳两级。还能跳三级import java.math.BigDecimal;import java.util.Scanner;public class Main{ public static void main(String[]args){ Scanner reader=new Scanner(System.in); while(reader.hasNext()){ _java 递归例题
文章浏览阅读1.5k次,点赞6次,收藏6次。目录1.串应用- 计算一个串的最长的真前后缀题目描述输入输出样例输入样例输出题解2.字符串替换(string)题目描述输入输出样例输入样例输出题解3.可重叠子串 (Ver. I)题目描述输入输出样例输入样例输出题解4.字符串操作(string)题目描述输入输出样例输入样例输出题解1.串应用- 计算一个串的最长的真前后缀题目描述给定一个串,如ABCDAB,则ABCDAB的真前缀有:{ A, AB,ABC, ABCD, ABCDA }ABCDAB的真后缀有:{ B, AB,DAB, CDAB, BCDAB_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。
文章浏览阅读68次。西安交通大学/算法设计与问题求解/树与二叉树/MOOC_算法设计与问题求解西安交通大学
文章浏览阅读1.6k次。问题:在Vue项目中出现如下错误提示:[Vue warn]: Computed property "totalPrice" was assigned to but it has no setter. (found in <Anonymous>)代码:<input v-model="totalPrice"/>原因:v-model命令,因Vue 的双向数据绑定原理 , 会自动操作 totalPrice, 对其进行set 操作而 totalPrice 作为计..._computed property "totalprice" was assigned to but it has no setter.
文章浏览阅读60次。十分暴力而简洁的解决方式:读取P和T的位置并自动生成唯一正确答案,将题给测点与之对比,不一样就给我爬!_basic 1003 case 1
文章浏览阅读422次。原标题:详解将Web项目War包部署到Tomcat服务器基本步骤详解将Web项目War包部署到Tomcat服务器基本步骤1 War包War包一般是在进行Web开发时,通常是一个网站Project下的所有源码的集合,里面包含前台HTML/CSS/JS的代码,也包含Java的代码。当开发人员在自己的开发机器上调试所有代码并通过后,为了交给测试人员测试和未来进行产品发布,都需要将开发人员的源码打包成Wa..._/opt/bosssoft/war/medical-web.war/web-inf/web.xml of module medical-web.war.
文章浏览阅读3k次,点赞3次,收藏13次。# -*- coding: utf-8 -*-# 简述:这里有四个数字,分别是:1、2、3、4#提问:能组成多少个互不相同且无重复数字的三位数?各是多少?def f(n):list=[]count=0for i in range(1,n+1):for j in range(1, n+1):for k in range(1, n+1):if i!=j and j!=k and i!=k:list.a..._python求从0到9任意组合成三位数数字不能重复并输出
文章浏览阅读1k次,点赞3次,收藏2次。<el-table-column prop="studentSex" label="性别" :formatter="sex"></el-table-column>然后就在vue的methods中写方法就OK了methods: { sex(row,index){ if(row.studentSex == 1){ return '男'; }else{ return '女'; }..._elementui table 性别
文章浏览阅读1.1k次。java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下