Spring 学习笔记(五)—— Bean之间的关系、作用域、自动装配
继承
Spring提供了配置信息的继承机制,可以通过为<bean>元素指定parent值重用已有的<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="baseuser" class="Demo05.BaseUser">
<property name="userid" value="1"/>
<property name="username" value="rekent"/>
<property name="password" value="123"/>
</bean>
<bean id="user1" parent="baseuser">
<property name="userid" value="2"/>
</bean>
</beans>
例如:上述我创建了一个BaseUser,其后的只要继承了BaseUser的Bean都会有BaseUser的配置信息,此时只需要重写不同的部分即可。
注意:这里的继承是指配置信息的重用,与面向对象的继承毫无关系。另外,Spring并没有要求配置信息存在继承关系的两个Bean是统一类型的,只要具有相关属性即可。
依赖
Spring 通过Bean之间的引用ref建立了所有Bean之间的完整依赖关系,当实例化一个Bean时,IoC容器能保证该Bean所依赖的其他Bean已经初始化完毕。
但是有时,可能要求Bean A的初始化必须在Bean B的初始化之后,而B不是A的属性,因此无法通过向A注入B来保证首先完成B的创建。
此时便提供了depends-on属性来指定前置依赖的Bean。例如:
<bean id="father" class=""></bean>
<bean id="son" class="" depends-on="father"></bean>
作用域
作用域通过<bean>元素的scope属性指定,Spring支持5种作用域。
作用域 |
描述 |
---|---|
singleton |
一个Bean定义对应唯一一个对象实例,Bean以单实例的方式存在(默认) |
prototype |
一个Bean定义对应多个对象实例,每次调用getBean()时,就创建一个新实例(开销大,不推荐) |
request |
(仅在基于Web的SpringApplicationContext情形下有效)在一次Http请求中,一个Bean定义对应一个实例,即每个请求都会有各自的Bean。 |
session |
(仅在基于Web的SpringApplicationContext情形下有效)在一个HtppSession中,一个Bean定义对应一个实例。 |
global session |
(仅在基于Web的SpringApplicationContext情形下有效)在一个全局的Http Session中,一个Bean定义对应一个实例。 |
自动装配(源于他人,原文链接:http://www.cnblogs.com/sysman/p/4485199.html)
可以使用bean元素的autowire属性指定自动装配的类型,spring支持如下类型:
自动装配的类型 |
描述 |
---|---|
no/default |
autowire="no"指定spring不使用自动装配,需要手动装配 |
byName |
按照bean属性的名字从spring容器中找同名的bean进行注入,适用于setter注入 |
byType |
按照bean属性的类型从spring容器中找相同类型的bean进行注入,适用于setter注入 |
constructor |
按照类型装配,跟byType类似.适用于构造器参数注入 |
下面我们将分别讲解着四种装配类型
不使用自动装配-no
我们之前讲解的所有的例子都属于这种类型.在这种情况下所有bean的装配都是手动进行的.我们再用一个例子复习下
1.新建包com.tutorialspoint.autowire,并在包中新建Cat.java、Dog.java、Duck.java.后面所有例子都会用到这三个类:
//Cat.java
package com.tutorialspoint.autowire;
public class Cat {
public void sayHi(){
System.out.println("miao miao ... ");
}
}
//Dog.java
package com.tutorialspoint.autowire;
public class Dog {
public void sayHi(){
System.out.println("wang wang ... ");
}
}
//Duck.java
package com.tutorialspoint.autowire;
public class Duck {
public void sayHi(){
System.out.println("ga ga ... ");
}
}
2.新建包com.tutorialspoint.autowire.no,并在包中新建Zoo.java,内容如下:
package com.tutorialspoint.autowire.no;
import com.tutorialspoint.autowire.*;
public class Zoo {
private Cat cat;
private Dog dog;
private Duck duck;
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public void setDuck(Duck duck) {
this.duck = duck;
}
public void print(){
if(cat==null){
System.out.println("cat is null");
}else{
cat.sayHi();
}
if(dog==null){
System.out.println("dog is null");
}else{
dog.sayHi();
}
if(duck==null){
System.out.println("duck is null");
}else{
duck.sayHi();
}
}
}
3.在src目录下新建autowire_no.xml配置文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="cat" class="com.tutorialspoint.autowire.Cat"></bean>
<bean id="dog" class="com.tutorialspoint.autowire.Dog"></bean>
<bean id="duck" class="com.tutorialspoint.autowire.Duck"></bean>
<bean id="zoo" class="com.tutorialspoint.autowire.no.Zoo">
<property name="cat" ref="cat"></property>
<property name="dog" ref="dog"></property>
</bean>
</beans>
4.在com.tutorialspoint.autowire.no包中新建MainApp.java.内容如下:
package com.tutorialspoint.autowire.no;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("autowire_no.xml");
Zoo zoo = (Zoo) context.getBean("zoo");
zoo.print();
}
}
5.运行程序,检查结果:
通过上面的程序我们可以得出如下结论:
手动装配bean,bean的所有依赖项都要在bean元素中明确指定.如果不进行指定spring容器就不会注入该属性.
按照名字进行自动装配-byName
在byName装配方式下,spring首先会反射autowire="byName"的bean,得到bean中的所有属性名(根据setter推算),然后从容
器中寻找同名的bean,最后把找到的bean注入到当前bean中.我们还是用代码说话:
1.新建包com.tutorialspoint.autowire.byname,并在包中新建Zoo.java类.内容如下:
package com.tutorialspoint.autowire.byname;
import com.tutorialspoint.autowire.Cat;
import com.tutorialspoint.autowire.Dog;
import com.tutorialspoint.autowire.Duck;
public class Zoo {
private Cat cat;
private Dog dog;
private Duck duck;
// 自动装配并不适用于原始类型.这时候我们可以对该属性进行手动装配
private String zooName;
public void setZooName(String zooName) {
this.zooName = zooName;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public void setDuck(Duck duck) {
this.duck = duck;
}
public void print() {
if (cat == null) {
System.out.println("cat is null");
} else {
cat.sayHi();
}
if (dog == null) {
System.out.println("dog is null");
} else {
dog.sayHi();
}
if (duck == null) {
System.out.println("duck is null");
} else {
duck.sayHi();
}
System.out.println(zooName);
}
}
2.在src目录下新建autowire_byName.xml配置文件.内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 名为zoo的bean在按照byName进行装配的时候,可以适配名字为cat、dog
的bean,不能适配名字为duck1的bean。所以最终zoo中会注入进cat和dog
不会注入duck. -->
<bean id="cat" class="com.tutorialspoint.autowire.Cat"></bean>
<bean id="dog" class="com.tutorialspoint.autowire.Dog"></bean>
<bean id="duck1" class="com.tutorialspoint.autowire.Duck"></bean>
<bean id="zoo" class="com.tutorialspoint.autowire.byname.Zoo" autowire="byName">
<!-- 由于自动装配仅适用于引用类型,普通类型还需要手动进行注入 -->
<property name="zooName" value="international_zoo"></property>
</bean>
</beans>
3.在包com.tutorialspoint.autowire.byname中新建MainApp.java.内容如下:
package com.tutorialspoint.autowire.byname;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("autowire_byName.xml");
Zoo zoo = (Zoo)context.getBean("zoo");
zoo.print();
}
}
4.运行代码,检查结果:
分析结果可以看到cat和dog已经按照属性名字自动装配到了zoo中.duck1由于没有匹配的属性名所以没有进行装配.zooName是
我们手动进行注入的。
按照类型进行自动装配-byType
在byType装配方式下,spring首先会反射autowire="byType"的bean,得到bean属性的返回类型,然后去spring容器中按照类
型去匹配,最后把匹配到的bean注入到当前bean中.看个例子就明白了:
1.新建包com.tutorialspoint.autowire.bytype,并在包中新建Zoo.java类,内容如下:
package com.tutorialspoint.autowire.bytype;
import com.tutorialspoint.autowire.Cat;
import com.tutorialspoint.autowire.Dog;
import com.tutorialspoint.autowire.Duck;
public class Zoo {
private Cat cat;
private Dog dog;
private Duck duck;
// 自动装配并不适用于原始类型.这时候我们可以对该属性进行手动装配
private String zooName;
public void setZooName(String zooName) {
this.zooName = zooName;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public void setDuck(Duck duck) {
this.duck = duck;
}
public void print() {
if (cat == null) {
System.out.println("cat is null");
} else {
cat.sayHi();
}
if (dog == null) {
System.out.println("dog is null");
} else {
dog.sayHi();
}
if (duck == null) {
System.out.println("duck is null");
} else {
duck.sayHi();
}
System.out.println(zooName);
}
}
2.在src目录下新建配置文件autowire_byType.xml。内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- 名为zoo的bean在按照byType进行装配的时候,可以适配名字为cat1、dog1、duck1
的bean的类型。所以最终cat1、dog1、duck1会被分别注入进zoo的cat、dog、duck属性。
在按照类型进行装配的时候,如过有两个bean的类型符合的话,spring就不知道最终该使用哪个,这时候我们
可以使用primary="true"告诉spring优先使用本bean
-->
<bean id="cat1" class="com.tutorialspoint.autowire.Cat" primary="true"></bean>
<bean id="cat2" class="com.tutorialspoint.autowire.Cat"></bean>
<bean id="dog1" class="com.tutorialspoint.autowire.Dog"></bean>
<bean id="duck1" class="com.tutorialspoint.autowire.Duck"></bean>
<bean id="zoo" class="com.tutorialspoint.autowire.bytype.Zoo" autowire="byType">
<!-- 由于自动装配仅适用于引用类型,普通类型还需要手动进行注入 -->
<property name="zooName" value="international_zoo"></property>
</bean>
</beans>
3.在包com.tutorialspoint.autowire.bytype中新建MainApp.java。内容如下:
package com.tutorialspoint.autowire.bytype;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("autowire_byType.xml");
Zoo zoo = (Zoo)context.getBean("zoo");
zoo.print();
}
}
4.运行程序,检查结果:
构造器参数类型自动装配-constructor
在constructor自动装配模式下,spring首先会反射bean的构造函数,得出构造函数的参数的类型,然后起spring容器中匹配合适的
类型的bean,最后使用构造器参数注入的方法把符合的bean注入到当前bean中。看代码:
1.新建包com.tutorialspoint.autowire.constructor,并在包中新建Zoo.java。内容如下:
package com.tutorialspoint.autowire.constructor;
import com.tutorialspoint.autowire.*;
public class Zoo {
private Cat cat;
private Dog dog;
private Duck duck;
private String zooName;
public Zoo(Cat cat, Dog dog, Duck duck, String zooName) {
this.cat = cat;
this.dog = dog;
this.duck = duck;
this.zooName = zooName;
}
public void print() {
if (cat == null) {
System.out.println("cat is null");
} else {
cat.sayHi();
}
if (dog == null) {
System.out.println("dog is null");
} else {
dog.sayHi();
}
if (duck == null) {
System.out.println("duck is null");
} else {
duck.sayHi();
}
System.out.println(zooName);
}
}
2.在src目录下新建autowire_constructor.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- constructor跟byType十分相似.
名为zoo的bean在按照constructor进行装配的时候,可以适配名字为cat1、dog1、duck1
的bean的类型。所以最终cat1、dog1、duck1会被分别注入进zoo的cat、dog、duck属性(使用
构造器参数进行注入)。
在按照constructor进行装配的时候,如过有两个bean的类型符合的话,spring就不知道最终该使用哪个,这时候我们
可以使用primary="true"告诉spring优先使用本bean
-->
<bean id="cat1" class="com.tutorialspoint.autowire.Cat" primary="true"></bean>
<bean id="cat2" class="com.tutorialspoint.autowire.Cat"></bean>
<bean id="dog" class="com.tutorialspoint.autowire.Dog"></bean>
<bean id="duck1" class="com.tutorialspoint.autowire.Duck"></bean>
<bean id="zoo" class="com.tutorialspoint.autowire.constructor.Zoo" autowire="constructor">
<!-- 由于自动装配仅适用于引用类型,普通类型还需要手动进行注入 -->
<constructor-arg name="zooName" value="international_zoo"></constructor-arg>
</bean>
</beans>
3.在com.tutorialspoint.autowire.constructor包中新建MainApp.java。内容如下:
package com.tutorialspoint.autowire.constructor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("autowire_constructor.xml");
Zoo zoo = (Zoo)context.getBean("zoo");
zoo.print();
}
}
4.运行程序,检查结果:
如果使用sping的自动装配,本人不推荐使用xml的配置方式.最好使用注解的配置方式。原因如下:
1.基于xml的自动装配粒度态度。默认会装配所有符合条件的bean.不能指定哪个属性不进行自动装配
2.不能指定哪些属性必须进行装配,否则抛出异常.
以上两点使用spring的注解配置元数据都是可以做到的。我们下节就讲解spring注解配置元数据。
- 【干货】大数据量下,58同城mysql实践!
- 如何预先处理电影评论数据以进行情感分析
- 如何在Python中从零开始实现随机森林
- 教程从头开始在Python中实现k最近邻居
- 建立安全的 AI
- Python NLTK 自然语言处理入门与例程
- 漏洞预警 | Apache Struts2 曝任意代码执行漏洞 (S2-045,CVE-2017-5638)
- 详解OSSIM-OSSEC WIN 4771案例
- JSShell:一个基于python的交互式Shell
- golang中操作excel
- 企业安全漏洞通告引擎
- 通过httprouter和redis框架搭建restful api服务
- .NET Core 实现定时抓取博客园首页文章信息并发送到邮箱
- 基于 R 语言和 SPSS 的决策树算法介绍及应用
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Autonomous_driving_application_Car_detection_v3a
- Python实现图片相似度计算
- Python实现在原始视频上添加动态雪花
- Three.js学习|代码详解 个人见解
- Linux进程详解
- Face_Recognition_v3a
- Building_a_Recurrent_Neural_Network_Step_by_Step_v3b
- gym 搭建 RL 环境
- MNIST练习
- Dinosaurus_Island_Character_level_language_model_final_v3b
- Trigger_word_detection_v1a
- 《深入浅出SQL》问答录(二)
- 《深入浅出SQL》问答录(四)
- 《深入浅出MySQL》问答录(五)
- 《深入浅出SQL》问答录(七)