spring 配置bean 怎么使用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring 配置bean 怎么使用相关的知识,希望对你有一定的参考价值。
参考技术A 1、Bean的配置一般都在XML文件中进行配置2、Bean相关包为:org.springframework.beans和org.springframework.context
3、spring的Bean管理的实现是依靠大量的反射来实现的。
4、Bean定义配置
4.1 Bean标签
▶id属性:用于指定Bean的名称,在Bean被依赖时使用,在获取Bean时使用等
▶name属性:用于指定Bean的别名
▶class属性:用于指定Bean的来源,即创建要创建的Bean的class类(需要全限定名)
▶singleton属性:用于指定当前Bean的创建模式,若值为true表示为单例模式,false表示原型模式(prototype)
▶depends-on属性:用于指定当前Bean的依赖Bean,强制指定的Bean在当前Bean初始化之前先完成初始化
▶init-method属性:用于指定当前Bean的初始化方法,在Bean实例创建好后,首先会调用其指定名称的方法
▶destory-method属性:用于指定当前Bean的销毁方法,在Bean即将被销毁之前会自动调用该属性指定的方法
▶lazy-init属性:用于指定当前Bean的初始化时间,若值为true表示在初次调用时才会自动创建实例并初始化,false表示在IoC容器创建的时候就会完成创建和初始化
▶autowire属性:用于指定当前Bean的依赖关系的自动注入方式,其有五个值:
▷byName值:表示通过id名称来自动匹配;
▷byType值:表示通过class指定的类型来自动装配;
▷constructor值:表示使用构造函数的参数进行自动装配(参数的类型匹配);
▷autodetect值:表示自动进行选择匹配方式,首先进行constructor自动装配,若不存在构造方法则使用byType方式进行自动装配;
▷no值:表示不适用自动装配。
▶dependency-check属性:用于指定Bean的依赖检查模式,检查依赖关系是否完整,与自动装配合用,其有四个值:
▷simple值:表示针对基本类型、字符串、集合进行依赖检查
▷object值:表示对引用对象进行依赖检查
▷all值:表示对基本类型、字符串、集合、引用对象全部进行依赖检查
▷none值:表示不进行任何依赖检查,默认情况。
Bean示例:
1 <?xml version=”1.0”encoding=”utf-8”?>
2 <!Doctype beans PUBLIC “-//SPRING//DTD BEAN//EN”
3 “http://www.springframework.org/dtd/spring-beans.dtd”>
4 <beans>
5 <bean id=”helloworld” class=”com.dh.spring.HelloWorld” singleton=”true” depends-on=”date” lazy-init=”false” init-mathod=”init” destory-method=”destory”/>
6 <bean id=”date” class=”java.util.Date”/>
7 </beans>
4.2 property标签
▶name属性:用于指定属性的名称,与类中的set方法后方的名称一致
▶value属性:用于指定该属性的值,用于指定的值是基本类型、字符串类型
▶ref属性:用于指定该属性的值,用于指定的值是引用对象类型(即其他的Bean),ref后面的值为另一个Bean的id
▶value标签:用于指定属性的值,类型为基本类型、字符串类型,值为标签内的文本内容,可以使用null值将属性的值设置为null
▶ref标签:用于指定属性的值,类型为引用对象类型,值为其属性的值,其属性有以下三种:
▷local属性:用于指定依赖本地Bean实例,即同一XML文件中定义的Bean
▷bean属性:用于指定依赖的Bean实例,可以是不同XML文件中的Bean
▷parent属性:用于指定依赖的Bean实例,可以是当前BeanFactory或ApplicationContext的父BeanFactory或ApplicationContext中的Bean
以下是针对集合的标签
▶list标签:用于声明该依赖对象为一个list集合,其下用value和ref标签来指定list中的各值(基本、字符串、对象等)
▷value标签:用于指定list集合中的值,指定的值为基本类型、字符串类型,值为文本内容
▷ref标签:用于指定list集合中的引用值,指定的值为其他的对象Bean,其用法与之前property标签下的ref标签的用法相同
▶set标签:用于声明该依赖对象为一个set集合,其用法与list标签相同。
▶map标签:用于声明该依赖对象为一个map集合,其下用entry标签来声明一个键值对
▷entry标签:用于声明map集合下的一个键值对,其下用key属性指明键,value/ref标签指明值
→key属性:用于指明键值对中的键,它一般为字符串
→value标签:用于指明键值对中的值,类型为基本类型、字符串类型
→ref标签:用于指明键值对中的值,类型为引用对象类型,即其他的Bean,其用法同之前的ref标签
map实例1:
1 <bean id=”helloworld” class=”com.dh.spring.HelloWorld”>
2 <property name=”pname”>
3 <map>
4 <entry key=”mkey1”>
5 <value>mvalue1</value>
6 </entry>
7 <entry key=”mkey2”>
8 <value>mvalue2</value>
9 </entry>
10 </map>
11 </property>
12 </bean>
map实例2:
1 <bean id=”helloworld2” class=”com.dh.spring.HelloWorld2”>
2 <property name=”pname”>
3 <map>
4 <entry key=”mkey1”>
5 <ref bean=”helloworld”/>
6 </entry>
7 </map>
8 </property>
9 </bean>
▶props标签:用于声明该依赖对象为一个properties集合,其下用prop标签来指定属性的名称及值(键值对)
▷prop标签:用于设置集合中的一个键值对
→key属性:用于指明键值对中的键,一般为字符串
→文本内容:用于指明键值对中的值,一般为字符串,不用加引号
props实例:
1 <bean id=”helloword” class=”com.dh.spring.HelloWorld”>
2 <property name=”pname”>
3 <props>
4 <prop key=”pkey1”>pvalue1</prop>
5 <prop key=”pkey2”>pvalue2</prop>
6 </props>
7 </property>
8 </bean>
5、Bean的生命周期
Bean的生命周期包括Bean的定义,Bean的初始化,Bean的使用,Bean的销毁
Bean的定义:一般Bean使用XML文件的方式进行定义,定义的时候将Bean之间的依赖关系和属性的赋值都进行了定义
Bean的初始化:其实Bean的初始化包括Bean的创建和初始化两个方法,Bean的创建和初始化一般是同步进行的,Bean在完成创建后直接就会进行初始化操作,创建的时机与Bean的lazy-init属性的设置有关。
Bean的使用:在web程序运行期间,发生对某一个Bean的调用时,就会使用这个Bean实例,如果使用编码的方式来获取Bean同样也是Bean的使用,Bean的编码使用方式有三种,第一种是使用BeanWarpper,第二种是使用BeanFactory,第三种就是使用ApplicationContext。
Bean的销毁:Bean实例在程序退出的时候会进行销毁,而在销毁之前会自动调用Bean的destory-method属性指定名称的方法。
Spring之Bean的注入
Bean的配置中介绍的是Bean声明问题,在哪声明怎么声明的问题。Bean的注入是怎么实例化,怎么注入的问题。Bean注入的方式有两种,一种是在XML中配置,另一种则是使用注解的方式注入。
一、XML方式注入
XML方式注入一般有三种方式:属性注入、构造函数注入和工厂方法注入。
一、属性注入
在传统的对象实例化时可以通过new class(),然后通过setXXX()方法设置对象的属性值或依赖对象,属性注入也是采用这种方式,只是Spring框架会在内部完成这些操作,它会先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。它会使用默认的构造函数(无参数构造函数),只需为注入的属性设置set方法,可选择性和灵活性比较高,所以也是比较常用的一种注入方式。这里示例还是在IOC章节使用人和空气的基础上稍作修改来演示。IAir接口和CleanAir、DirtyAir类不变,这里就不贴了。
1.新建XMLInstance类
package com.demo.model; public class XMLInstance { private String name; public void setName(String name) { this.name = name; } private IAir air; public void setAir(IAir air) { this.air = air; } public void Breath() { System.out.println("Name:"+this.name+";Air:"+this.air.toString()); } public XMLInstance(String name, IAir air) { super(); this.name = name; this.air = air; } public XMLInstance() { } public void DestoryMethod() { System.out.println("DestoryMethod"); } public void InitMethod() { System.out.println("InitMethod"); } }
在XMLInstance类中并未声明构造函数,对于air属性只设置了set方法,get方法也没设置。
<bean id="CleanAir" class="com.demo.model.CleanAir"> <qualifier value="cleanair"/> </bean> <bean id="xmlinstance" class="com.demo.model.XMLInstance"> <property name="air" ref="CleanAir"></property> <property name="name" value="abc"></property> </bean>
Xml中使用property类配置属性,name是属性名,value用来设置基本数据类型的属性值。Spring配置文件中bean之间可以相互引用,引用时可以用<ref>标签配置bean的id属性使用。<ref>可以用在<property>属性中,也可以用在<construct-arg>构造函数的参数值,还可以用在其他地方,通过引用能减少bean的声明。
二、构造函数注入
在属性注入时先使用默认的构造函数(无参数构造函数)实例化,然后通过set方法注入属性,在传统实例化对象时可以自定义构造函数进行实例化,构造函数注入就是通过自定义构造函数来进行对象的实例化。这里在XMLInstance类的基础上增加了一个构造函数,第一个参数是String类型的name,第二个参数是IAir类型的air。
public XMLInstance(String name, IAir air) { super(); this.name = name; this.air = air; }
Xml中使用使用<construect-arg>来设置构造函数的参数,index属性设置参数的顺序,参数顺序应该与构造函数的一致,ref设置引用bean的id,value设置构造函数参数的值。
<bean id="xmlcontructinstance" class="com.demo.model.XMLInstance"> <constructor-arg index="1" ref="CleanAir"></constructor-arg> <constructor-arg index="0" value="abc"></constructor-arg> </bean>
三、工厂方法注入
工厂方法注入参考的是工厂设计模式,通过在工厂类中实现对象的实例化。工厂类负责创建一个或多个目标类实例,工厂类方法一般以接口或抽象类变量的形式返回目标类实例,工厂类对外屏蔽了目标类的实例化步骤,调用者甚至不用知道具体的目标类是什么。工厂方法也分静态工厂方法和非静态工厂方法,静态工厂方式不用实例化工厂类,直接通过类名调用,非静态工厂方法需要先实例化工厂类,然后通过工厂类对象调用获取对象。这里创建了一个工厂类XMLFactory,在类中定义了一个静态方法,和一个实例方法用来实例化bean对象。
package com.demo.model; public class XMLFactory { public XMLInstance CreateInstance() { return new XMLInstance("instance",new CleanAir()); } public static XMLInstance CreateStaticInstance() { return new XMLInstance("static instance",new CleanAir()); } }
1.静态工厂方法
只需设置工厂方法对应的类,以及对应的工厂方法。
<bean id="xmlfactorystaticinstance" class="com.demo.model.XMLFactory" factory-method="CreateStaticInstance"></bean>
2.实例工厂方法
需要先实例化工厂类,再通过工厂类对象调用实例方法获取bean对象。
<bean id="xmlfactoryinstance" factory-bean="xmlfactory" factory-method="CreateInstance" destroy-method="DestoryMethod" init-method="InitMethod"></bean>
四、常见数据类型注入
(1)List属性注入
使用<list>配置java.util.List类型的属性。List属性中元素可以是任何数据类型的值,如果是Java对象可以使用ref指定,或使用<bean>定义新实例。如果是基础数据类型可直接用字符串。<list>中的元素会按配置的先后顺序排序。
<property name="lists">
<list>
<value>1</value>
<ref bean="CleanAir" />
<bean class="com.demo.model.CleanAir"/>
</list>
</property>
(2)Set属性注入
使用<set>配置java.util.Set类型的属性。Set属性中元素可以是任何数据类型的值,如果是Java对象可以使用ref指定,或使用<bean>定义新实例。如果是基础数据类型可直接用字符串。<set>中的元素没有先后顺序。
<property name="sets"> <set> <value>1</value> <ref bean="CleanAir" /> <bean class="com.demo.model.CleanAir"/> </set> </property>
(3)Map属性注入
使用<map>配置java.util.Map类型的属性。<entry>配置Map里的元素,Key指定索引,value指定值。如果是Java对象可以使用ref指定,或使用<bean>定义新实例。
<property name="maps"> <map> <entry key="key1" value="1"></entry> <entry key="key2" value-ref="CleanAir"></entry> <entry key="key3" > <bean class="com.demo.model.CleanAir"/> </entry> </map> </property>
(4)Properties属性注入
使用<props>配置java.util.Properties类型的属性。<props>配置一个Properties对象,<prop>配置一条属性,属性Key配置索引。
<property name="pros"> <props> <prop key="prokey1">prokeyA</prop> <prop key="prokey2">prokeyB</prop> </props> </property>
(5)自定义属性编辑器
对于有一些属性是没法注入的,此时就需要自定义,比如日期类型。可以通过继承PropertyEditorSupport的类,重写setAsText方法来实现注入。这里定义了CustomerProperty继承PropertyEditorSupport,重写了setAsText方法,并将该bean配置到xml中。
package com.demo.model; import java.beans.PropertyEditorSupport; import java.text.ParseException; import java.text.SimpleDateFormat; public class CustomerProperty extends PropertyEditorSupport { private String format="yyyy-MM-dd"; public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } @Override public void setAsText(String text) throws IllegalArgumentException { SimpleDateFormat sdf=new SimpleDateFormat(format); //super.setAsText(text); try { //转换对象,能过setValue方法重新赋值 this.setValue(sdf.parse(text)); } catch (ParseException e) { e.printStackTrace(); } } }
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date" value="com.demo.model.CustomerProperty"/> </map> </property> </bean>
配置之后就可以注入Date类型的属性了。
<property name="date" value="2018-8-20"/>
这里新建了XmlCollectionsDemo类,配置了上面的几个类型的属性来演示。
package com.demo.model; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class XmlCollectionsDemo { private List<Object> list; private Properties pros; private Set<Object> sets; private Map<String,Object> maps; private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public List<Object> list() { return list; } public void setLists(List<Object> list) { this.list = list; } public Properties getPros() { return pros; } public void setPros(Properties pros) { this.pros = pros; } public Set<Object> getSets() { return sets; } public void setSets(Set<Object> sets) { this.sets = sets; } public Map<String, Object> getMaps() { return maps; } public void setMaps(Map<String, Object> maps) { this.maps = maps; } public static void main( String[] args ) throws Exception { ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"ApplicationContext.xml"}); BeanFactory factory=context; XmlCollectionsDemo annontationInstance=(XmlCollectionsDemo)factory.getBean("xmlCollectionsDemo"); System.out.println(annontationInstance.list); System.out.println(annontationInstance.pros); System.out.println(annontationInstance.sets); System.out.println(annontationInstance.maps); System.out.println(annontationInstance.date); } }
<bean id="xmlCollectionsDemo" class="com.demo.model.XmlCollectionsDemo"> <property name="lists"> <list> <value>1</value> <ref bean="CleanAir" /> <bean class="com.demo.model.CleanAir"/> </list> </property> <property name="sets"> <set> <value>1</value> <ref bean="CleanAir" /> <bean class="com.demo.model.CleanAir"/> </set> </property> <property name="maps"> <map> <entry key="key1" value="1"></entry> <entry key="key2" value-ref="CleanAir"></entry> <entry key="key3" > <bean class="com.demo.model.CleanAir"/> </entry> </map> </property> <property name="pros"> <props> <prop key="prokey1">prokeyA</prop> <prop key="prokey2">prokeyB</prop> </props> </property> <property name="date" value="2018-8-20"/> </bean>
通过运行main方法,打印出属性值。
[1, CleanAir, CleanAir]
{prokey2=prokeyB, prokey1=prokeyA}
[1, CleanAir, CleanAir]
{key1=1, key2=CleanAir, key3=CleanAir}
Mon Aug 20 00:00:00 CST 2018
五、初始化函数、销毁函数
通过上面3种注入方式的学习也对通过xml对bean实例化有的了解,有的对象在实例化之后还需要执行某些初始化代码,但这些初始化代码还不能写在构造函数中,此时可以将初始化代码写到某个方法中,将init-method属性值设置为该方法,Spring会强制执行该方法进行初始化。而又的对象在使用完毕之后需要释放,可以使用destroy-method来进行销毁。
public void DestoryMethod() { System.out.println("DestoryMethod"); } public void InitMethod() { System.out.println("InitMethod"); }
这里先在XMLInstance类中增加了上面两个方法来模拟销毁和初始化方法。然后在xml配置bean时就可以设置destroy-method、init-method属性的值对应两个方法的方法名。注解中@PostConstruct对应init-method,@PreDestory对应destroy-method。
<bean id="xmlfactoryinstance" factory-bean="xmlfactory" factory-method="CreateInstance" destroy-method="DestoryMethod" init-method="InitMethod"></bean>
二、注解注入方式
一、常用注解介绍
学习完XML注入之后再学习注解方式注入就容易的多,注解方式注入主要涉及到@Autowired,@Resource,@Required,@Qualifier,@Value这几个注解。在第2章节的2.2.4IOC实例中定义Person时就使用过@Autowired、@Qualifier。下面来了解下它们具体用法。
@Autowired:默认是按类型匹配注入bean,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。在使用@Autowired时,首先在容器中查询对应类型的bean,如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据,如果查询的结果不止一个,那么@Autowired会根据名称来查找。如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false。
@Required:适用于bean属性setter方法,并表示受影响的bean属性必须在XML配置文件在配置时进行填充。否则,容器会抛出一个BeanInitializationException异常。
@Qualifier:@Autowired默认是单实例的,但是在面向接口编程中,如果把一个属性设置为接口类型,一个接口可能有多个实现,那到底是注入哪一个呢?为了解决这个问题,就有了@Qualifier。
@Value:在xml配置属性时可以通过property的value设置默认值,@Value也可以为属性设置默认值。
@Resource:默认按名称匹配注入bean。要求提供一个bean名称的属性,如果属性为空,则自动采用标注处的变量名或方法名作为bean的名称。如果我们没有在使用@Resource时指定bean的名字,同时Spring容器中又没有该名字的bean,这时候@Resource就会退化为@Autowired即按照类型注入。
package com.demo.model; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Required; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class AnnontationInstance { @Value("abc") private String name; public void setName(String name) { this.name = name; } //@Resource与@Autowired两者选其一 // @Autowired // @Qualifier(value="cleanair") private IAir air; @Resource(name="CleanAir") public void setAir(IAir air) { this.air = air; } public void Breath() { System.out.println("Name:"+this.name+";Air:"+this.air.toString()); } }
上面代码使用@Value注解为name设置了默认值,使用@Resources设置bean的名称为IAir属性注入bean,也可以使用@[email protected]为IAir注入bean。
二、开启注解
上面配置完注解之后,还要告诉Spring开启注解,这样@Autowired、@Resources这些注解才起作用。开启有两种比较简单的方式。
1.在xml配置文件中使用context:annotation-config
<context:annotation-config />
2.在xml配置文件中使用context:component-scan
<context:component-scan base-package="com.demo.model"/>
以上是关于spring 配置bean 怎么使用的主要内容,如果未能解决你的问题,请参考以下文章
spring自动扫描的bean可以注入xml中配置的bean吗?