第二章 装配Bean
装配:创建对象之间写作关系的行为
2.1声明Bean
2.1.1创建spring配置
创建spring配置,创建一个springbean.xml的文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 6 7 8 </beans>
<beans>内部可以放置spring的所有配置信息,包括<bean>的声明
2.1.2声明一个简单的bean
首先:创建的maven的工程(maven的配置以及eclipse配置maven捣鼓了半天);
下面是每个文件的代码:
pom.xml文件,就不介绍pom.xml文件了(自己也不是很熟),只要在<dependency>标签里配置上依赖的jar包,若是本地maven仓库里有jar包,就不会下载,若是没有,就会自动去下载(前提是装了maven),而且会自动把包导入到Maven Dependencies(就是上图中倒数第二个箭头的文件)包类库中:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 2 <modelVersion>4.0.0</modelVersion> 3 <groupId>com.siaction.chapter01</groupId> 4 <artifactId>chapter01</artifactId> 5 <version>0.0.1-SNAPSHOT</version> 6 7 <dependencies> 8 <!-- log4j的依赖 --> 9 <dependency> 10 <groupId>log4j</groupId> 11 <artifactId>log4j</artifactId> 12 <version>1.2.14</version> 13 </dependency> 14 <!-- junit的依赖 --> 15 <dependency> 16 <groupId>junit</groupId> 17 <artifactId>junit</artifactId> 18 <version>4.11</version> 19 <scope>test</scope> 20 </dependency> 21 <!-- spring beans的依赖 --> 22 <dependency> 23 <groupId>org.springframework</groupId> 24 <artifactId>spring-beans</artifactId> 25 <version>4.2.9.RELEASE</version> 26 </dependency> 27 <!-- spring context(应用上下文的依赖) --> 28 <dependency> 29 <groupId>org.springframework</groupId> 30 <artifactId>spring-context</artifactId> 31 <version>4.2.9.RELEASE</version> 32 </dependency> 33 34 </dependencies> 35 </project>
springbean.xml文件:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 6 7 <!-- 名字为duke的bean --> 8 <bean id="duke" class="com.springinaction.springidol.Juggler"></bean> 9 10 </beans>
log4j.properties的文件,这个文件通用的,哪里都能找到:
1 # Global logging configuration\uff0c\u5efa\u8bae\u5f00\u53d1\u73af\u5883\u4e2d\u8981\u7528debug 2 log4j.rootLogger=DEBUG, stdout 3 # Console output... 4 log4j.appender.stdout=org.apache.log4j.ConsoleAppender 5 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 6 log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
Performer接口
1 package com.springinaction.springidol; 2 3 /** 4 * 表演者的接口 5 */ 6 public interface Performer { 7 8 /** 9 * 表演的方法 10 * @throws Exception 11 */ 12 void perform() throws Exception; 13 14 15 }
Juggler实现类:
1 package com.springinaction.springidol; 2 3 /** 4 * Performer的一个实现类:Juggler 5 * 6 */ 7 public class Juggler implements Performer { 8 9 //Juggler有一个豆袋子,初始值是3 10 private int beanBags = 3; 11 12 public Juggler(){} 13 14 public Juggler(int beanBags){ 15 this.beanBags = beanBags; 16 } 17 18 //表演抛豆袋子 19 public void perform() throws Exception { 20 21 System.out.println("JUGGLING "+beanBags+" BENABAGS"); 22 23 } 24 25 }
TestCase测试用例:
1 package com.springinaction.test; 2 3 import org.junit.Test; 4 import org.springframework.context.ApplicationContext; 5 import org.springframework.context.support.ClassPathXmlApplicationContext; 6 7 import com.springinaction.springidol.Performer; 8 9 10 public class TestCase { 11 12 //这个ClassPathXmlApplicationContext是springframe-context中 13 //org.springframework.context.support包下的类 14 ApplicationContext ac = new ClassPathXmlApplicationContext("spring/springbean.xml");//注意路径 15 16 @Test 17 public void testPerformer() throws Exception { 18 19 Performer duke = (Performer) ac.getBean("duke"); 20 duke.perform(); 21 22 } 23 24 }
结果,注意这里的bean是单例的bean,上面语句debug有说明(singleton bean 'duke'):
2.1.3构造器注入bean
此时,将springbean.xml文件中的duke bean的标签中加点内容,注意这个要有对应的构造函数,就是上述中的有参数的构造函数:
1 <!-- 名字为duke的bean --> 2 <bean id="duke" class="com.springinaction.springidol.Juggler"> 3 <!-- 通过构造器为beanBags赋值 --> 4 <constructor-arg value="15"/> 5 </bean>
下面分别是通过构造器注入对象引用和工厂方法(factory-method)获得bean(其他的代码就不展示了,最下面有源码):
1 <!-- 声明一个sonnet29的bean --> 2 <bean id="sonnet29" class="com.springinaction.springidol.Sonnet29"></bean> 3 4 <!--声明一个PoeticJuggler的bean,并且通过构造器注入,对应的引用,ref位引用依赖的bean --> 5 <bean id="poeticDuke" class="com.springinaction.springidol.PoeticJuggler"> 6 <constructor-arg value="15"/> 7 <constructor-arg ref="sonnet29"/> 8 </bean> 9 10 <!-- Stage是个到单例类, 构造函数私有化 11 factory-method='方法名' 12 创建bean的时候,就调用这个方法 13 --> 14 <bean id="theStage" class="com.springinaction.springidol.Stage" factory-method="getInstance"></bean>
2.1.4 Bean的作用域
spring所有的bean默认都是单例的。<bean>有scope属性设置成prototype就变成多例的了;
1 <!-- scope='prototype'就变成多例 --> 2 <bean id="ticket" class="com.springinaction.springidol.Ticket" scope="prototype"></bean>
测试:
1 //测试多例bean 2 @Test 3 public void testTicket() throws Exception { 4 5 Ticket ticket1 = (Ticket) ac.getBean("ticket"); 6 Ticket ticket2 = (Ticket) ac.getBean("ticket"); 7 8 System.out.println(ticket1==ticket2);//结果是false 9 10 }
scope的取值:
2.1.5 初始化和销毁bean
init-method和destory-method方法,为bean定义初始化和销毁操作(bean的属性);
init-method属性指定了在初始化Bean时要调用的方法。
destory-method属性指定了Bean从容器移除之前要调用的方法。
若是很多bean有相同的名字的初始化和销毁方法,可以为<beans>标签中加上default-init-method='方法名' ,default-destroy-method='方法名';
2.2注入Bean属性
2.2.1 通过setter注入简单值
<bean><property name="" value="" ></property></bean>;name的值是bean的属性,value的值是将要赋的值;
1 <!-- com.springinaction.springidol.Instrumentalist 2 这个类有一个song的属性,现在赋值为“认真的雪”; 3 注意:这个类一定要有setter方法, 4 没有setter方法抛出NotWritablePropertyException 5 --> 6 <bean id="kenny" 7 class="com.springinaction.springidol.Instrumentalist"> 8 <property name="song" value="认真的雪"></property> 9 </bean>
2.2.2 引用其他Bean
<property>属性ref="" 就是引用另一个bean
1 <!-- 乐器:saxophone --> 2 <bean id="saxophone" class="com.springinaction.springidol.Saxophone"></bean> 3 <!-- ref='saxophone',直接引用上边的bean --> 4 <bean id="kenny" 5 class="com.springinaction.springidol.Instrumentalist"> 6 <property name="song" value="认真的雪"></property> 7 <property name="instrument" ref="saxophone"></property> 8 </bean> 9
上述方式,多个bean都引用saxophone,那他们就共用了一个bean,不共用的方法,注入内部bean:
1 <!-- 注入内部bean,就避免了多个音乐家共用一个saxophone而产生的卫生问题 --> 2 <bean id="kenny" 3 class="com.springinaction.springidol.Instrumentalist"> 4 <property name="song" value="认真的雪"></property> 5 <property name="instrument"> 6 <bean class="com.springinaction.springidol.Saxophone"></bean> 7 </property> 8 </bean>
2.2.3 使用Spring的命名空间p装配属性
首先要在<beans>中引入p装配的命名空间:xmlns:p="http://www.springframework.org/schema/p"
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:p="http://www.springframework.org/schema/p" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> 7 8 <!-- p装配,可以和最开始的那个空容器对比多了xmlns:p="http://www.springframework.org/schema/p" --> 9 <bean id="kenny1" 10 class="com.springinaction.springidol.Instrumentalist" 11 p:song="认真的雨" 12 p:instrument-ref="saxophone"/> 13 14 </beans>
2.2.4 装配集合
list装配,<ref>引用Spring上下文中的其他bean的引用,数组也可以同样装配,:
1 <!-- 乐器:guitar 吉他 --> 2 <bean id="guitar" class="com.springinaction.springidol.Guitar"></bean> 3 <!-- 乐器:cymbal 钹 --> 4 <bean id="cymbal" class="com.springinaction.springidol.Cymbal"></bean> 5 <!-- 乐器:harmonica 口琴 --> 6 <bean id="harmonica" class="com.springinaction.springidol.Harmonica"></bean> 7 <!-- 一个乐队 --> 8 <bean id="hank" 9 class="com.springinaction.springidol.OneManBand"> 10 <property name="instruments"> 11 <list> 12 <ref bean="guitar"/> 13 <ref bean="cymbal"/> 14 <ref bean="harmonica"/> 15 </list> 16 </property> 17 </bean>
set装配,下面4个<ref>,有一个是重复的,set里面只装一个:
1 <bean id="hank1" 2 class="com.springinaction.springidol.OneManBand"> 3 <property name="instruments"> 4 <set> 5 <ref bean="guitar"/> 6 <ref bean="cymbal"/> 7 <ref bean="harmonica"/> 8 <ref bean="harmonica"/> 9 </set> 10 </property> 11 </bean>
map装配<map><entry key="" value-ref=""></map>:
1 <bean id="hank2" 2 class="com.springinaction.springidol.OneManBand"> 3 <property name="instruments"> 4 <map> 5 <entry key="GUITAR" value-ref="guitar"/> 6 <entry key="CYMBAL" value-ref="cymbal"/> 7 <entry key="HARMONICA" value-ref="harmonica"/> 8 </map> 9 </property> 10 </bean>
properties集合装配,注意和map的区别:
1 <bean id="hank3" 2 class="com.springinaction.springidol.OneManBand"> 3 <property name="instruments"> 4 <props> 5 <prop key="GUITAR">GUITAR GUITAR GUITAR</prop> 6 <prop key="CYMBAL">CYMBAL CYMBAL CYMBAL</prop> 7 <prop key="HARMONICA">HARMONICA HARMONICA HARMONICA</prop> 8 </props> 9 </property> 10 </bean>
2.2.4 装配空值
只需<property name="属性名"><null></property>,这样就是ok了
2.3使用表达式装配Bean
这个感觉暂时用不上,就先不看了,以后回来再看;