spring-第五篇之spring容器中的bean
1、bean的基本定义和bean别名
2、容器中bean的作用域
singleton:单例模式,在整个spring IoC容器中,singleton作用域的bean将只生成一个实例。
prototype:每次通过容器的getBean()方法获取prototype作用域的bean时,都将产生一个新的bean实例。
request:对于一次HTTP请求,request作用域的bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该bean,得到的总是同一个实例。只有在Web应用中使用spring时,该作用域才真正的有效。
session:对于一次HTTP会话,sesion作用域的bean将只生成一个实例,这意味着,在同一次HTTP会话内,程序每次请求该bean,得到的总是同一个实例。只有在Web应用中使用spring时,该作用域才真正的有效。
global session:每个全局的HTTP Session对应一个bean实例。在典型的情况下,仅在使用portlet context的时候有效。只有在Web应用中使用spring时,该作用域才真正的有效。
比较常用的是singleton和prototype。对于singleton作用域的bean,每次请求该bean都将获得相同的实例。容器负责跟踪bean实例的状态,负责维护bean实例的生命周期行为;对于prototype作用域的bean,程序每次请求该id的bean,spring都会新建一个bean实例,然后返回给程序。这种情况下,spring容器仅仅使用new关键字创建bean实例,一旦创建成功,容器就不再跟踪实例,也不会维护bean实例的状态。
如果不指定bean的作用域,spring容器默认使用singleton作用域。
spring配置文件通过scope属性指定bean的作用域,该属性可以接受singleton、prototype、request、session、globalSession五个值。
3、request作用域
4、session作用域
5、配置依赖
在依赖注入方式总结的时候,我们总结类两种依赖注入方式:
设值注入:通过<property.../>元素驱动spring执行setter方法。
构造注入:通过<constructor-arg.../>元素驱动spring执行带参数的构造器。
对这两种设值方式的底层实现模拟:
Person.java
package com.lfy.bean; public class Person { private String name;
private int age; /**
* 定义一个无参构造器
*/
public Person() {} /**
* 定义一个带参构造器
* @param name
* @param age 构造器使用Integer,class字段属性是int
*/
public Person(String name,Integer age) {
this.name=name;
this.age=age;
} public void sayHello(String name) { System.out.println(name+",Hello.Nice to see you.");
} public void selfIntroduction() { System.out.println("Hello,I am "+name+".I am "+age);
}
}
ReflexTest.java
package com.lfy.main; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import com.lfy.bean.Person; /**
* java反射的应用
* @author lfy
*
*/
public class ReflexTest { public static void main(String[] args) { /**
* spring设值注入底层代码实现简单例子
*/
try {
Class targetClass=Class.forName("com.lfy.bean.Person");
try {
Object bean=targetClass.newInstance();
try {
String name="lfy";
Method targetMethod=targetClass.getMethod("sayHello", name.getClass());//这里演示没有使用Person.name的setter方法,但道理一样的
try {
targetMethod.invoke(bean, name);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} /**
* spring构造注入底层实现简单例子
*/
try {
Class targetClass=Class.forName("com.lfy.bean.Person");
try {
String param1="lfy";
Integer param2=21;
Constructor targetCtr=targetClass.getConstructor(param1.getClass(),param2.getClass());
try {
//以指定构造器创建bean实例
Object bean=targetCtr.newInstance(param1,param2);
Person p=(Person)bean;
p.selfIntroduction();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果:
6、自动装配注入合作者bean(即:被依赖bean),缺点是明显降低了配置文件的可读性
<beans.../>元素下是default-autowire属性,<bean.../>元素下是autowire,它们可接受的值有:
no:不使用自动装配。bean依赖必须通过ref元素定义,是默认配置。
byName:根据setter方法名进行自动装配。spring容器查找容器中的全部bean,找出其id与setter方法名去掉set前缀,并小写字母后同名的bean来完成注入。如果没有匹配到任何bean实例,spring不会进行任何注入。
byType:根据setter方法的形参类型来自动装配。spring容器查找容器中的全部bean,如果正好有一个bean类型与setter方法的形参类型匹配,就自动注入这个bean;如果找到多个这样的bean,就抛出一个异常;如果没有找到这样的bean,则什么都不发生,setter方法不会被调用。
constructor:与byType类似,区别是用于自动匹配构造器的参数。如果容器不能恰好找到一个与构造器参数类型匹配的bean,则会抛出一个异常。
autodetect:spring容器根据bean内部结构,自行决定使用constructor或byType策略。如果找到一个默认的构造器,那么就会应用byType策略。
7、注入嵌套bean
如果某个bean所依赖的bean不想被spring容器直接访问,则可以使用嵌套bean。
将<bean.../>配置成<property.../>或<constructor-args.../>的子元素,则该bean仅作为设值注入、构造注入的参数,该bean就叫做嵌套bean。由于容器不能获取嵌套bean,故无需配置嵌套bean的id属性。
8、注入集合值
如果要被注入的值是集合类型,无论设值注入,还是构造注入,则可以使用集合元素<list.../>、<set.../>、<map.../>和<props.../>分别来设值类型为List、Set、Map和Properties的集合参数值。
看个例子:
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="stoneAxe" class="com.lfy.impl.StoneAxe"/>
<bean id="steelAxe" class="com.lfy.impl.SteelAxe"/> <bean id="chinese" class="com.lfy.impl.Chinese"> <!-- List<String> -->
<property name="schools">
<list>
<!-- 每个value、ref、bean...都配置一个List元素 -->
<value>小学</value>
<value>中学</value>
<value>大学</value>
</list>
</property> <!-- Map -->
<property name="scores">
<map>
<!-- 每个entry代表一个key-value对 -->
<entry key="数学" value="87"/>
<entry key="英语" value="89"/>
<entry key="语文" value="82"/>
</map>
</property> <!-- Map<String,Axe> -->
<property name="phaseAxes">
<map>
<entry key="原始社会" value-ref="stoneAxe"/>
<entry key="农业社会" value-ref="steelAxe"/>
</map>
</property> <!-- Properties -->
<property name="health">
<props>
<!-- 每个prop元素配置一个属性项,其中key指定属性名 -->
<prop key="血压">正常</prop>
<prop key="血压">175</prop>
</props>
</property> <!-- Set -->
<property name="axes">
<set>
<!-- 每个value、ref、bean...都配置一个Set元素 -->
<value>普通的字符串</value>
<bean class="com.lfy.impl.SteelAxe"/>
<ref bean="stoneAxe"/>
<list>
<value>20</value>
<!-- 再次为List配置一个Set集合作为元素 -->
<set>
<value type="int">30</value>
</set>
</list>
</set>
</property> <!-- String[] -->
<property name="books">
<list>
<!-- 每个value、ref、bean...都配置一个数组元素 -->
<value>疯狂java讲义</value>
<value>疯狂Android讲义</value>
<value>轻量级java ee企业应用实战</value>
</list>
</property>
</bean>
</beans>
stoneAxe.java
package com.lfy.impl; import com.lfy.bean.Axe; public class StoneAxe implements Axe { @Override
public String chop() {
return "石斧砍柴好慢";
} }
steelAxe.java
package com.lfy.impl; import com.lfy.bean.Axe; public class SteelAxe implements Axe { @Override
public String chop() {
return "钢斧砍柴真快";
} }
Chinese.java
package com.lfy.impl; import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set; import com.lfy.bean.Axe;
import com.lfy.bean.Person; public class Chinese implements Person { private Axe axe;
private List<String> schools;
private Map scores;
private Map<String,Axe> phaseAxes;
private Properties health;
private Set axes;
private String[] books; public Chinese() { System.out.println("spring实例化主调bean:Chinese实例...");
} //设值注入所需的setter方法
public void setAxe(Axe axe) {
this.axe=axe;
} public void setSchools(List schools) {
this.schools=schools;
} public void setScores(Map scores) {
this.scores=scores;
} public void setPhaseAxes(Map<String,Axe> phaseAxes) {
this.phaseAxes=phaseAxes;
} public void setHealth(Properties health) {
this.health=health;
} public void setAxes(Set axes) {
this.axes=axes;
} public void setBooks(String[] books) {
this.books=books;
} @Override
public void useAxe() {
//调用axe的chop()方法
//表明Person对象依赖于axe对象
System.out.println(axe.chop());
} public void test() { System.out.println(schools);
System.out.println(scores);
System.out.println(phaseAxes);
System.out.println(health);
System.out.println(axes);
System.out.println(Arrays.toString(books));
} }
springTest.java
package com.lfy.main; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lfy.impl.Chinese; public class SpringTest { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
Chinese c=ctx.getBean("chinese", Chinese.class);
c.test();
} }
运行结果:
9、组合属性的设值
举个例子,猫组合了一个主人相关的属性:
Chinese.java
package com.lfy.impl; import com.lfy.bean.Person; public class Chinese implements Person { //姓名
private String name; public String getName() { return name;
} public void setName(String name) { this.name=name;
}
}
Cat.java
package com.lfy.impl; import com.lfy.bean.Animal; public class Cat implements Animal { //猫的主人是个中国人
private Chinese chinese=new Chinese(); public Chinese getChinese() { return chinese;
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="cat" class="com.lfy.impl.Cat">
<property name="chinese.name" value="lfy"/>
</bean>
</beans>
SpringTest.java
package com.lfy.main; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lfy.impl.Cat;
import com.lfy.impl.Chinese; public class SpringTest { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
Cat c=ctx.getBean("cat", Cat.class);
System.out.println("猫的主人的名字叫做:"+c.getChinese().getName());
} }
运行结果:
spring-第五篇之spring容器中的bean的更多相关文章
- spring源码 — 二、从容器中获取Bean
getBean 上一节中说明了容器的初始化,也就是把Bean的定义GenericBeanDefinition放到了容器中,但是并没有初始化这些Bean.那么Bean什么时候会初始化呢? 在程序第一个主 ...
- 【String注解驱动开发】如何按照条件向Spring容器中注册bean?这次我懂了!!
写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,不 ...
- Spring第五篇
在Spring第四篇中 我们主要介绍了set get的注入方式 在Spring第五篇中 我们主要介绍使用注解配置Spring 主要分为两个步骤 1 导包的同时引入新得约束 导包如下 1.1 重写注解代 ...
- 从Spring容器中获取Bean。ApplicationContextAware
引言:我们从几个方面有逻辑的讲述如何从Spring容器中获取Bean.(新手勿喷) 1.我们的目的是什么? 2.方法是什么(可变的细节)? 3.方法的原理是什么(不变的本质)? 1.我们的目的是什么? ...
- String框架搭建的基本步骤,及从 IOC & DI 容器中获取 Bean(spring框架bean的配置)--有实现数据库连接池的链接
Spring框架的插件springsource-tool-suite-3.4.0.RELEASE-e4.3.1-updatesite(是一个压缩包)导入步骤: eclipse->help-> ...
- Spring容器中的Bean
一,配置合作者的Bean Bean设置的属性值是容器中的另一个Bean实力,使用<ref.../>元素,可制定一个bean属性,该属性用于指定容器中其他Bean实例的id属性 <be ...
- 在listener或者工具中使用spring容器中的bean实例
在项目中经常遇见需要在Listener中或者工具中使用Spring容器中的bean实例,由于bean不能在stataic的类中使用. 介绍一种方式: public class SpringTool { ...
- FastJson序列化Json自定义返回字段,普通类从spring容器中获取bean
前言: 数据库的字段比如:price:1 ,返回需要price:1元. 这时两种途径修改: ① 比如sql中修改或者是在实体类转json前遍历修改. ②返回json,序列化时候修改.用到的是fastj ...
- spring 在容器中一个bean依赖另一个bean 需要通过ref方式注入进去 通过构造器 或property
spring 在容器中一个bean依赖另一个bean 需要通过ref方式注入进去 通过构造器 或property
- 7 -- Spring的基本用法 -- 5... Spring容器中的Bean;容器中Bean的作用域;配置依赖;
7.5 Spring容器中的Bean 7.5.1 Bean的基本定义和Bean别名 <beans.../>元素是Spring配置文件的根元素,该元素可以指定如下属性: default-la ...
随机推荐
- React框架新闻网站学习过程中遇到的错误总结
1.安装指定版本插件命令 npm install 插件名字@1.1.4(版本号) --save 或 yarn add 插件名字@1.1.4(版本号) --dev 2.Error:‘Link’ is n ...
- 基于firebird的数据转存
功能:使用于相同的表从一个数据库转存到另一数据库: 方式:直连fdb并加载django,引用django的model完成: 原因:1.select * from *** 返回的数有很多None,直接i ...
- [Usaco2007 Jan]Telephone Lines架设电话线(最短路,二分)
[Usaco2007 Jan]Telephone Lines架设电话线 Description FarmerJohn打算将电话线引到自己的农场,但电信公司并不打算为他提供免费服务.于是,FJ必须为此向 ...
- win7提示不是正版桌面变黑
1.以管理员身份运行cmd.exe 2.在该界面>后面输入SLMGR -REARM,大家注意下有个空格键 然后点击确定,重启电脑就OK了.
- ps:图层知识
如果我们要改变下左图上方的蓝色小球位置,就需要先创建一个符合小球大小的选区,这并不困难,可以使用椭圆选框工具来创建一个正圆的选区(可通过[空格 CTRL 单击图像]放大图像).之后使用移动工具移动选区 ...
- 安装phpredis扩展以及phpRedisAdmin工具
先从phpredis的git拿到最新的源码包:wget https://github.com/nicolasff/phpredis/archive/master.tar.gz 然后解压到进入目录:ta ...
- git点滴
git指定版本,SHA-1短的,长的都可以 git checkout c66a9be git checkout c66a9befsadf1sdf1s3fd21 git log ##查询本地log gi ...
- python全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)
昨日内容回顾 线程 什么是线程? 线程是cpu调度的最小单位 进程是资源分配的最小单位 进程和线程是什么关系? 线程是在进程中的一个执行单位 多进程 本质上开启的这个进程里就有一个线程 多线程 单纯的 ...
- nodejs通过async/await来操作MySQL
在nodejs中从数据库得到数据后是通过回调函数来操作数据的,如果嵌套多层将非常可怕,代码逻辑和可读性将变得非常差.有时用promise也并不能很好得解决问题,因为如果用了promise后,代码将会有 ...
- The Cats' Feeding Spots
The Cats' Feeding Spots 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 In Yan Yuan, the Peking University cam ...