欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Bean的自动装配及作用域

程序员文章站 2022-03-10 16:04:14
1.XML配置里的Bean自动装配 Spring IOC 容器可以自动装配 Bean,需要做的仅仅是在 的 autowire 属性里指定自动装配的模式。自动装配方式有: byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, ......

1.xml配置里的bean自动装配

spring ioc 容器可以自动装配 bean,需要做的仅仅是在 <bean> 的 autowire 属性里指定自动装配的模式。自动装配方式有:

  • bytype(根据类型自动装配): 若 ioc 容器中有多个与目标 bean 类型一致的 bean. 在这种情况下, spring 将无法判定哪个 bean 最合适该属性, 所以不能执行自动装配.
  • byname(根据名称自动装配): 必须将目标 bean 的名称和属性名设置的完全相同.

示例代码:

person.java,person里面有三个属性:name,address,car。

package com.java.spring.autowire;

public class person {
	private string name;
	private address address;
	private car car;
	public string getname() {
		return name;
	}
	public void setname(string name) {
		this.name = name;
	}
	public address getaddress() {
		return address;
	}
	public void setaddress(address address) {
		this.address = address;
	}
	public car getcar() {
		return car;
	}
	public void setcar(car car) {
		this.car = car;
	}
	@override
	public string tostring() {
		return "person [name=" + name + ", address=" + address + ", car=" + car + "]";
	}
}

address.java

package com.java.spring.autowire;

public class address {
	private string city;
	private string street;
	public string getcity() {
		return city;
	}
	public void setcity(string city) {
		this.city = city;
	}
	public string getstreet() {
		return street;
	}
	public void setstreet(string street) {
		this.street = street;
	}
	@override
	public string tostring() {
		return "address [city=" + city + ", street=" + street + "]";
	}
}

car.java

package com.java.spring.autowire;

public class car {

	private string brand;
	private double price;
	public string getbrand() {
		return brand;
	}
	public void setbrand(string brand) {
		this.brand = brand;
	}
	public double getprice() {
		return price;
	}
	public void setprice(double price) {
		this.price = price;
	}
	@override
	public string tostring() {
		return "car [brand=" + brand + ", price=" + price + "]";
	}
}

1.1 使用byname进行自动装配

使用byname根据bean的名字和当前bean的setter风格的属性名进行自动装配,若有匹配的自动转配,没有匹配的赋值为空。

<bean id="address" class="com.java.spring.autowire.address" p:city="上海" p:street="南京路"></bean>
<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="person" class="com.java.spring.autowire.person" p:name="tom" autowire="byname"></bean>

运行后输出:

person [name=tom, address=address [city=上海, street=南京路], car=car [brand=audi, price=500000.0]]

若配置如下:

<bean id="address1212" class="com.java.spring.autowire.address" p:city="上海" p:street="南京路"></bean>
<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="person" class="com.java.spring.autowire.person" p:name="tom" autowire="byname"></bean>

address1212与setter风格的属性名address不一致,则address不能被赋值:

person [name=tom, address=null, car=car [brand=audi, price=500000.0]]

1.2 使用bytype进行自动装配

bytype根据bean的类型和当前bean的属性的类型进行自动装配,若ioc容器中有1个以上的类型匹配的bean,则抛异常。

<bean id="address" class="com.java.spring.autowire.address" p:city="上海" p:street="南京路"></bean>
<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="person" class="com.java.spring.autowire.person" p:name="tom" autowire="bytype"></bean>

运行后输出:

person [name=tom, address=address [city=上海, street=南京路], car=car [brand=audi, price=500000.0]]

若配置如下:

<bean id="address" class="com.java.spring.autowire.address" p:city="上海" p:street="南京路"></bean>
<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="car1231" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="person" class="com.java.spring.autowire.person" p:name="tom" autowire="bytype"></bean>

抛异常显示:(原因是有两个car类型的bean)

caused by: org.springframework.beans.factory.nouniquebeandefinitionexception: no qualifying bean of type [com.java.spring.autowire.car] is defined: expected single matching bean but found 2: car,car1231

在 bean 配置文件里设置 autowire 属性进行自动装配将会装配 bean 的所有属性. 然而, 若只希望装配个别属性时, autowire 属性就不够灵活了. autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些。

2.bean之间的关系:继承和依赖

2.1 spring 允许继承 bean 的配置, 被继承的 bean 称为父 bean. 继承这个父 bean 的 bean 称为子 bean。子 bean可以 从父 bean 中继承配置, 包括 bean 的属性配置,子 bean 也可以覆盖从父 bean 继承过来的配置。

<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="car2" class="com.java.spring.autowire.car" p:price="300000.0000" parent="car"></bean>

在主方法中获取bean实例:

car car=(car) ctx.getbean("car2");

 运行后输出:

car [brand=audi, price=300000.0]

2.2 父 bean 可以作为配置模板, 也可以作为 bean 实例. 若只想把父 bean 作为模板, 可以设置 <bean> 的abstract 属性为 true, 这样 spring 将不会实例化这个 bean。

若设置为抽象bean,则不能被实例化。

<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000" abstract="true"></bean>

在主方法中获取实例:

car car=(car) ctx.getbean("car");

报异常:

exception in thread "main" org.springframework.beans.factory.beanisabstractexception: error creating bean with name 'car': bean definition is abstract

并不是 <bean> 元素里的所有属性都会被继承. 比如: autowire, abstract 等.也可以忽略父 bean 的 class 属性, 让子 bean 指定自己的类, 而共享相同的属性配置. 但此时 abstract 必须设为 true。

2.2 spring 允许用户通过 depends-on 属性设定 bean 前置依赖的bean,前置依赖的 bean 会在本 bean 实例化之前创建好。如果前置依赖于多个 bean,则可以通过逗号,空格或的方式配置bean 的名称。

<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="person" class="com.java.spring.autowire.person" p:name="tom" p:address-ref="address" depends-on="car"></bean>

若没有配置car这个bean,则会报错。

3.bean的作用域

3.1 singleton

在 spring 中, 可以在 <bean> 元素的 scope 属性里设置 bean 的作用域. 默认情况下, spring 只为每个在 ioc 容器里声明的 bean 创建唯一一个实例, 整个 ioc 容器范围内都能共享该实例:所有后续的 getbean() 调用和 bean 引用都将返回这个唯一的 bean 实例.该作用域被称为singleton, 它是所有 bean 的默认作用域。

<bean id="address" class="com.java.spring.autowire.address" p:city="上海" p:street="南京路"></bean>
<bean id="car" class="com.java.spring.autowire.car" p:brand="audi" p:price="500000.0000"></bean>
<bean id="person" class="com.java.spring.autowire.person" p:name="tom" p:address-ref="address" p:car-ref="car"></bean>

在主方法中获取实例:

public class main {
	public static void main(string[] args){
		applicationcontext ctx=new classpathxmlapplicationcontext("beans-relation.xml");
		person person1=(person) ctx.getbean("person");
		person person2=(person) ctx.getbean("person");
		system.out.println(person1==person2);
	}

 system.out.println(person1==person2);打印结果为true,person1和person2为同一个对象。

3.2 prototype

原型的,容器初始化时不创建bean实例,而是在每次请求时都创建一个新的bean实例并返回。