【Spring4.0】 Spring中的Bean配置

##注意!!

此篇博文和上一篇博文有一些关联,如已经新建好的各种类的位置,如果对于类的位置不清楚请看上一篇博文
【Spring 4.0】Spring入门之第一个程序HelloWorld实现
##一、关于IOC和DI

    **IOC(Inversion of Control)控制反转:**其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式
    DI(Dependency Injection)依赖注入: IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接。




##二、Bean的配置

###(1)新建一个名为HelloWorld的JavaBean
(如果按照上一篇博文过来的朋友则不用做Bean的配置了,只需看一下解释就好。因为我是以上一篇的HelloWorld实例来讲解的)

public class HelloWorld {

	private String user;
	
	public HelloWorld() {
		System.out.println("HelloWorld's constructor...");
	}
	
	public void setUser(String user) {
		System.out.println("setUser:" + user);
		this.user = user;
	}
	
	public HelloWorld(String user) {
		this.user = user;
	}

	public void hello(){
		System.out.println("Hello: " + user);
	}
	
}

**HelloWorld.Java**
###(2)在`applicationContext`中为Bean中的属性赋值
<bean id="helloWorld" class="com.spring.helloworld.HelloWorld">
		<!-- 为属性赋值 -->
		<property name="user" value="Jerry"></property>
	</bean>

####属性解释:

属性 属性值
class bean 的 指的是HelloWorld的全路径名称,并且由于是通过反射方式创建Bean,因此Bean中必须有无参的构造器。如果没有无参构造器则会出错,当然如果没有显示声明构造器也无妨,因为虚拟机会隐式创建一个无参的构造器。
id 当创建好一个bean之后,如何引用这个bean呢?就需要使用id.它标识bean.并且id唯一。id:Bean 的名称:(1)在 IOC 容器中必须是唯一的。(2)若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字。(3)id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔。

###(3)在Main.java中通过容器读出数据

//1. 创建 Spring 的 IOC 容器
		//ApplicationContext:代表IOC容器
		//ClassPathXmlApplicationContext:是ApplicationContext接口的实现类
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		//2. 从 IOC 容器中获取 bean 的实例
		HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
		//根据类型来获取 bean 的实例: 要求在  IOC 容器中只有一个与之类型匹配的 bean, 若有多个则会抛出异常. 
		//一般情况下, 该方法可用, 因为一般情况下, 在一个 IOC 容器中一个类型对应的 bean 也只有一个. 
//		HelloWorld helloWorld1 = ctx.getBean(HelloWorld.class);
		//3. 使用 bean
		helloWorld.hello();

####注意!
    在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用。



###三、属性注入方式

在Spring中,致辞三种依赖注入的方式
####(1)属性注入

<!-- 配置一个 bean -->
	<bean id="helloWorld2" class="com.spring.helloworld.HelloWorld">
		<!-- 为属性赋值 -->
		<!-- 通过属性注入: 通过 setter 方法注入属性值 -->
		<property name="user" value="Tom"></property>
	</bean>

  • 属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象
  • 属性注入使用 <property>元素, 使用 name属性指定 Bean 的属性名称,value属性或 子节点指定属性值
  • 属性注入是实际应用中最常用的注入方式
    ####(2)构造器注入
    #####演示:
    ######1.添加Car类
public class Car {
	private String company;
	private String brand;
	private int maxSpeed;
	private float price;
	public Car(String company, String brand, float price) {
		super();
		this.company = company;
		this.brand = brand;
		this.price = price;
	}
	public Car(String company, String brand, int maxSpeed) {
		super();
		this.company = company;
		this.brand = brand;
		this.maxSpeed = maxSpeed;
	}
	public Car(String company, String brand, int maxSpeed, float price) {
		super();
		this.company = company;
		this.brand = brand;
		this.maxSpeed = maxSpeed;
		this.price = price;
	}
	@Override
	public String toString() {
		return "Car [company=" + company + ", brand=" + brand + ", maxSpeed="
				+ maxSpeed + ", price=" + price + "]";
	}
}

######2.配置bean:

<!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值? -->
	<!-- 可以根据 index 和 value 进行更加精确的定位. -->
	<bean id="car" class="com.spring.helloworld.Car">
		<constructor-arg value="KUGA" ></constructor-arg>
		<constructor-arg value="ChangAnFord" ></constructor-arg>
		<constructor-arg value="250000" ></constructor-arg>
	</bean>

######3.主方法调用:

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = (Car) ctx.getBean("car");
System.out.println(car);

######4.结果
这里写图片描述
#####注意!
    上面的构造器只是为了其中的前三个属性进行初始化,bean中的配置其实是按照顺序来初始化的,当然如果构造器非常多,如何对bean进行配置呢?

public Car(String company, String brand, float price) {
		super();
		this.company = company;
		this.brand = brand;
		this.price = price;
	}
	public Car(String company, String brand, int maxSpeed) {
		super();
		this.company = company;
		this.brand = brand;
		this.maxSpeed = maxSpeed;
	}

**(在Car类中增添两个构造器)**
######解决方案:
<bean id="car" class="com.spring.helloworld.Car">
		<constructor-arg value="KUGA" index="1"></constructor-arg>
		<constructor-arg value="ChangAnFord" index="0"></constructor-arg>
		<constructor-arg value="250000" type="float"></constructor-arg>
	</bean>
	<bean id="car3" class="com.spring.helloworld.Car">
		<constructor-arg value="BAOMA" type="java.lang.String"></constructor-arg>
		<constructor-arg value="ChangAnFord" type="java.lang.String"></constructor-arg>
		<constructor-arg value="250000" type="int"></constructor-arg>
	</bean>

  • (1)可以创建index:<constructor-arg value="audi" index="0"></constructor-arg>
  • (2)构造函数也是重载的,区分重载的是参数个数和类型,个数不同好办,相同的时候就可以在后面注明类型。
<constructor-arg value="BAOMA" type="java.lang.String"></constructor-arg>

**(使用 type来注明类型) **

结果:
这里写图片描述



###四、注入属性值细节

####(1)特殊字符
    字面值:可用字符串表示的值,可以通过<value> 元素标签或 value 属性进行注入。基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式。若字面值中包含特殊字符,如有尖括号<>等等,可以使用<![CDATA[]]> 把字面值包裹起来。

<bean id="car2" class="com.spring.helloworld.Car">
		<constructor-arg value="ChangAnMazda"></constructor-arg>
		<!-- 
		字面值也可以通过 <value> 元素标签
		若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) 
		-->
		<constructor-arg>
			<value><![CDATA[<ATARZA>]]></value>
		</constructor-arg>
		<constructor-arg value="180" type="int"></constructor-arg>
	</bean>

####(2)引用其他的Bean
    组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能。要使 Bean 能够相互访问, 就必须在 Bean 配置文件中指定对 Bean 的引用。在 Bean 的配置文件中, 可以通过<ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用。也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean。

<!-- 配置 bean -->
	<bean id="dao5" class="com.spring.ref.Dao"></bean>
	<bean id="service" class="com.spring.ref.Service">
		<!-- 通过 ref 属性值指定当前属性指向哪一个 bean! -->
		<property name="dao" ref="dao5"></property>
	</bean>

####(3)内部Bean
    当 Bean 实例仅仅给一个特定的属性使用时, 可以将其声明为内部 Bean. 内部 Bean 声明直接包含在<property><constructor-arg>元素里, 不需要设置任何 id 或 name 属性。内部 Bean 不能使用在任何其他地方。

<!-- 声明使用内部 bean -->
	<bean id="service2" class="com.spring.ref.Service">
		<property name="dao">
			<!-- 内部 bean, 类似于匿名内部类对象. 不能被外部的 bean 来引用, 也没有必要设置 id 属性 -->
			<bean class="com.spring.ref.Dao">
				<property name="dataSource" value="c3p0"></property>
			</bean>
		</property>
	</bean>

####(4)Null值
可以使用专用的<null/> 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值。

<bean id="dao2" class="com.spring.ref.Dao">
		<!-- 为 Dao 的 dataSource 属性赋值为 null, 若某一个 bean
		的属性值不是 null, 使用时需要为其设置为 null(了解) -->
		<property name="dataSource"><null/></property>
	</bean>

####(5)级联属性
和 Struts、Hiberante 等框架一样,Spring 支持级联属性的配置。

<bean id="action" class="com.spring.ref.Action">
		<property name="service" ref="service2"></property>
		<!-- 设置级联属性 -->
		<property name="service.dao.dataSource" value="DBCP2"></property>
</bean>

####(6)集合属性
在 Spring中可以通过一组内置的 xml 标签(例如: <list>, <set><map>) 来配置集合属性
#####1.配置java.util.List 类型的属性
需要指定<list>标签, 在标签里包含一些元素. 这些标签可以通过 <value>指定简单的常量值, 通过<ref> 指定对其他 Bean 的引用. 通过<bean>指定内置 Bean 定义. 通过<null/> 指定空元素. 甚至可以内嵌其他集合。

<!-- 装配集合属性 -->
	<bean id="user" class="com.spring.helloworld.User">
		<property name="userName" value="Jack"></property>
		<property name="cars">
			<!-- 使用 list 元素来装配集合属性 -->
			<list>
				<ref bean="car"/>
				<ref bean="car2"/>
			</list>
		</property>
	</bean>

######注意!
数组的定义和 List 一样, 都使用 <list>
#####2.配置java.util.Set类型的属性
java.util.Map通过 <map>标签定义, <map>标签里可以使用多个 <entry>作为子标签. 每个条目包含一个键和一个值。

<bean id="user7" class="com.spring.helloworld.User">
		<property name="userName" value="Rose"></property>
		<property name="wifeName" value="JACK"></property>
		<!-- 使用 Map 元素来装配集合属性  -->
		<property name="carmap">
			<map>
				<entry key="AA" value-ref="car"></entry>
				<entry key="BB" value-ref="car"></entry>
			</map>
		</property>
	</bean>

######注意!

  • 必须在<key> 标签里定义键
  • 因为键和值的类型没有限制, 所以可以自由地为它们指定 <value>, <ref>, <bean><null> 元素。
  • 可以将 Map 的键和值作为<entry> 的属性定义: 简单常量使用keyvalue来定义; Bean 引用通过 key-refvalue-ref属性定义。

#####3.配置java.util.Properties类型的属性
    使用 <props>定义java.util.Properties, 该标签使用多个 <prop> 作为子标签. 每个<prop> 标签必须定义key属性.实际应用于配置数据库连接池。
######第一步:新建DataSource类

import java.util.Properties;

public class DataSource {
	private Properties properties;
	public Properties getProperties() {
		return properties;
	}
	public void setProperties(Properties properties) {
		this.properties = properties;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "DataSoure [properties=" + properties +"]" ;
	}
}

######第二步:配置bean

<bean id="dataSource" class="com.spring.helloworld.DataSource">
		<property name="properties" >
			<props>
				<prop key="user">rout</prop>
				<prop key="password">rout</prop>
				<prop key="jdbcUrl">jdbc:mysql://localhost/hibernate</prop>
				<prop key="driverClass">com.mysql.jdbc.Driver</prop>
			</props>
		</property>
	</bean>

######第三步:打印相关信息

DataSource dataSource = (DataSource) ctx.getBean("dataSource");
System.out.println(dataSource);

######第四步:结果

DataSoure[properties={driverClass=com.mysql.jdbc.Driver, user=rout, password=rout, jdbcUrl=jdbc:mysql://localhost/hibernate}]

#####4.使用 utility scheme 定义集合
    使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合.。可以使用 util schema 里的集合标签定义独立的集合 Bean. 需要注意的是, 必须在<beans> 根元素里添加 util schema 定义。
######第一步:导入util命名空间
打开applicationContext如图按顺序设置
这里写图片描述
######第二步:使用util:list声明集合类型的 bean

<!-- 声明集合类型的 bean -->
	<util:list id="cars">
		<ref bean="car"/>
		<ref bean="car2"/>
	</util:list>
	<bean id="user2" class="com.spring.helloworld.User">
		<property name="userName" value="Rose"></property>
		<!-- 引用外部声明的 list -->
		<property name="cars" ref="cars"></property>
	</bean>

#####5.使用 p 命名空间
为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息。Spring 从 2.5 版本开始引入了一个新的 p 命名空间,可以通过<bean>元素属性的方式配置 Bean 的属性。使用 p 命名空间后,基于 XML 的配置方式将进一步简化。

<!-- 通过p命名空间为bean的属性赋值,需要导入p命名空间 -->
	<bean id="user3" class="com.spring.helloworld.User"
		p:cars-ref="cars" p:userName="Titannic"></bean>

猜你喜欢

转载自blog.csdn.net/qq_33596978/article/details/81081409