Spring 配置Bean
配置bean的形式(二种):
1.基于XML文件
2.基于注解
配置bean的方式(三种):
1.通过全类名(反射)
2.通过工厂方式(静态工厂/实例工厂)
3.FactoryBean
依赖注入方式(三种):
1.属性注入
2.构造器注入
3.工厂注入
注意事项:
都需要有默认的构造函数——无参的构造函数
如果没有写任何构造函数,系统则会自己创建一个默认的,如果有构造函数则不会创建
经过了解,但也没有证实,把配置和注入分为此三种,有的博客中把注入和配置搞混,导致有更多种的方式配置
1.属性注入(采用全类名反射配置bean)
使用<property>元素,使用name指定Bean的属性名称,value属性或<value>子节点指定属性值,需要在bean中有相应的set方法
有如下bean:
package com.chenx.spring.beans;
public class HelloWorld {
private String name;
public void setName(String name) {
this.name = name;
}
}
属性注入配置以上Bean如下:其中name指的是set方法的名字而不是字段的名称
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld">
<property name="name" value="ccc"></property>
</bean>
2.构造方法注入(采用全类名反射配置bean)
如上相同Bean配置,使用构造方法注入如下:需要在bean中有相应的构造方法
Bean:
package com.chenx.spring.beans;
public class HelloWorld {
private String name;
public HelloWorld(String name) {
this.name = name;
}
}
通过构造方法注入:
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld">
<constructor-arg value="ccc"></constructor-arg>
</bean>
(1)
从上方构造方法注入可以看到,只用到了value这个属性,那么如何知道value是ccc的这个值赋给哪一个参数呢,可以看到默认是采用按照顺序的方式的,现在,可以通过index来定位此value的位置,如下:
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld">
<constructor-arg value="ccc" index="0"></constructor-arg>
</bean>
(2)
如果在bean构造函数有另一个同样个数参数的构造方法,但是他们的类型不同,如此一来岂不是冲突了,现在,可以通过配置type——此字段的类型,来区分,如下:
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld">
<constructor-arg value="ccc" index="0" type="java.lang.String"></constructor-arg>
</bean>
(3)
构造方法注入的另一种写法:通过value子节点的方式
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld">
<constructor-arg>
<value type="java.lang.String">ccc</value>
</constructor-arg>
</bean>
(4)
若是注入值中包含特殊字符需要使用<![CDATA[.....]]>写入 ,如我写入<ccc>:
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld">
<constructor-arg>
<value type="java.lang.String"><![CDATA[<ccc>]]></value>
</constructor-arg>
</bean>
////////插入——属性方式注入和构造方式注入的一些细节
1.Bean的相互引用(属性注入方式)
如有一个student 的bean,在此bean中包含上面的helloworld的一个字段,此bean的配置方法如下:
studentBean:
package com.chenx.spring.beans;
public class Student {
private String name;
private String age;
private HelloWorld helloWorld;
public void setHelloWorld(HelloWorld helloWorld) {
this.helloWorld = helloWorld;
}
public void setName(String name) {
this.name = name;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
引用外部bean:student配置如下:通过ref 引用之前配置好的helloworld的bean (引用外部bean)
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="age" value="ds"></property>
<property name="name" value="123"></property>
<property name="helloWorld" ref="helloWorld"></property>
</bean>
或者是
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="age" value="ds"></property>
<property name="name" value="123"></property>
<property name="helloWorld">
<ref bean="helloWorld"></ref>
</property>
</bean>
引用内部bean:还可以通过自己创建引用内部bean:(只能在内部使用,不能被外部使用)
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="age" value="ds"></property>
<property name="name" value="123"></property>
<property name="helloWorld">
<bean class="com.chenx.spring.beans.HelloWorld">
<constructor-arg value="ccc"></constructor-arg>
</bean>
</property>
</bean>
2.Bean的相互引用(构造器注入方式)
如上相同的bean:采用构造器注入的方式
<bean id="student2" class="com.chenx.spring.beans.Student">
<constructor-arg value="dd"></constructor-arg>
<constructor-arg value="11"></constructor-arg>
<constructor-arg ref="helloWorld"></constructor-arg>
</bean>
3.null和级联属性
null:
<bean id="student2" class="com.chenx.spring.beans.Student">
<constructor-arg value="dd"></constructor-arg>
<constructor-arg value="11"></constructor-arg>
<constructor-arg><null/></constructor-arg>
</bean>
级联属性:
可以通过hellowrold.name 修改 参数值
注意点:
1.首先必须初始化此参数,也就是有<constructor-arg ref="helloWorld"></constructor-arg>(hellowWorld配置过)
2.因为用到了hellowrold.name 所以需要有helloworld的get的方法(set也要有) ,还得在Helloworld中有setName的方法
<bean id="student2" class="com.chenx.spring.beans.Student">
<constructor-arg value="dd"></constructor-arg>
<constructor-arg value="11"></constructor-arg>
<constructor-arg ref="helloWorld"></constructor-arg>
<property name="helloWorld.name" value="ss"></property>
</bean>
4.集合属性
(1)List(Set类似)
(外部bean)
在Student的里面加入List<HelloWorld> ,关于此来配置:(注意ref引入的需要都在同一个包中)
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="name" value="dd"></property>
<property name="age" value="111"></property>
<property name="helloWorldList">
<list>
<ref bean="helloWorld"></ref>
<ref bean="helloWorld"></ref>
</list>
</property>
</bean>
(内部bean)
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="name" value="dd"></property>
<property name="age" value="111"></property>
<property name="helloWorldList">
<list>
<bean class="com.chenx.spring.beans.HelloWorld">
<property name="name" value="11"></property>
</bean>
<bean class="com.chenx.spring.beans.HelloWorld">
<property name="name" value="12"></property>
</bean>
</list>
</property>
</bean>
(2)Map
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="name" value="dd"></property>
<property name="age" value="111"></property>
<property name="map">
<map>
<entry key="A" value-ref="helloWorld"></entry>
<entry key="B" value-ref="helloWorld"></entry>
</map>
</property>
</bean>
(3) Properties(可以用来存数据库连接信息)
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="name" value="dd"></property>
<property name="age" value="111"></property>
<property name="properties">
<props>
<prop key="username">xx</prop>
<prop key="password">xx</prop>
<prop key="driverclass">xx</prop>
<prop key="url">xxx</prop>
</props>
</property>
</bean>
5.使用util scheme配置独立的Bean, 以便多次共享引用
在配置的过程中会遇到配置bean的时候,创建重复的代码,现在创建一个独立的bean以供相同引用的代码使用,无需再重复编写
<bean id="student" class="com.chenx.spring.beans.Student">
<property name="name" value="dd"></property>
<property name="age" value="111"></property>
<property name="list" ref="hellos"></property>
</bean>
<util:list id="hellos">
<ref bean="helloWorld"></ref>
<ref bean="helloWorld"></ref>
<ref bean="helloWorld"></ref>
<ref bean="helloWorld"></ref>
</util:list>
6.使用p命名空间 为Bean的属性赋值
为了简化Xml文件的配置
<bean id="student" class="com.chenx.spring.beans.Student" p:name="yy" p:age="rr" p:list-ref="hellos"></bean>
7.自动装配
Spring IOC容器可以帮助我们自动装配Bean 只需要在<bean>的autowire属性里指定自动装配模式
byType:根据类型自动装配,如果有多个类型相同的bean,则不能装配
byName:根据名称自动装配,必须将目标Bean的名称和属性名完全相同
此方式有缺陷,一旦配置则会匹配所有属性,不够灵活
<bean id="student" class="com.chenx.spring.beans.Student" p:name="yy" p:age="rr" autowire="byName"></bean>
8.继承
使用parent 属性 继承配置 ,被继承的bean称为父bean,继承这个bean的bean是子bean
子bean中父bean中继承其属性,子bean也可覆盖bean中的属性
父bean可用作模板,也可作为实例,可使用属性abstract抽象属性配置bean使其不可作为实例,只能被继承
<bean id="student" class="com.chenx.spring.beans.Student" p:name="yy" p:age="rr"></bean>
<bean id="student2" class="com.chenx.spring.beans.Student" parent="student" p:name="pp"></bean>
作为abstrace bean 用作继承:(一个bean如果没有class 其必须是抽象bean)autowire,abstract不会被继承
<bean id="student" p:name="yy" p:age="rr" abstract="true"></bean>
<bean id="student2" class="com.chenx.spring.beans.Student" parent="student" p:name="pp"></bean>
9.依赖
Spring通过depends-on属性设定bean前置依赖的bean ,前置依赖bean会在本bean实例化之前先创建好
如果有多个依赖,可以通过逗号,空格方式配置bean的名称(依赖并不是把其配置到此bean中,只是在此之前必须配置此依赖的bean)
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld" p:name="111"></bean>
<bean id="student" class="com.chenx.spring.beans.Student" p:name="yy"
p:age="rr" depends-on="helloWorld" ></bean>
10.作用域
使用scope属性来配置bean的作用域
singleton:单例:默认值 :容器初始化时创建bean实例,在整个容器的生命周期里只创建这一个bean,换句话说,通过getBean()获取到的实例都是同一个。
prototype:多例: 容器初始话的时候不创建bean的实例,而在每次请求时都创建一个新的bean实例,并返回
<bean id="helloWorld" class="com.chenx.spring.beans.HelloWorld" p:name="111" scope="prototype"></bean>
3.工厂方式注入(采用静态工厂方法配置)
介绍完属性方法注入和构造器注入之后介绍静态方法注入,可以看出来,属性和构造器其实不同之处在于bean中一个是使用set方法一个是使用构造器的方式,在配置文件中相应的一个使用property 属性参数,一个使用constructor-arg进行配置。
全类名反射配置:像是在配置文件中说明你要什么,然后IOC就会自动把相应的东西给你
工厂方式配置:像是多了一个环节,在属性和构造器的基础上多了一个膜具的工厂(需要自己配置膜具),工厂提供了一个窗口,然后你需要在配置文件中告知此窗口你需要哪个膜具(只需要膜具的名称),接着就会帮你自动注入
总结:相比而言,全类名反射配置有点像自己造膜具,而工厂方式像是自己造膜具,接着取膜具,全类名反射配置显然少了一个步骤更方便。
静态工厂方式配置:
首先创建工厂(staticfactory),创建膜具(map),开辟窗口(getmap)
package com.chenx.spring.beans;
import java.util.HashMap;
import java.util.Map;
public class StaticFactory {
private static Map<String,HelloWorld> map=new HashMap<String,HelloWorld>();
static {
map.put("aa",new HelloWorld("1"));
map.put("bb",new HelloWorld("2"));
}
public static HelloWorld getMap(String name) {
return map.get(name);
}
}
工厂方式注入具体配置:哪个工厂(class), 哪个窗口(factory-method), 哪个膜具(constructor-arg)
<bean id="helloWorld" factory-method="getMap" class="com.chenx.spring.beans.StaticFactory">
<constructor-arg value="aa"></constructor-arg>
</bean>
4.工厂方法注入(采用实例工厂方法配置)
实例工厂方式和静态工厂方式注入有点类似,也需要加一个工厂的bean,只不过把static去了
package com.chenx.spring.beans;
import java.util.HashMap;
import java.util.Map;
public class InstanceFactory {
private Map<String,HelloWorld> map=null;
public InstanceFactory(){
map=new HashMap<String,HelloWorld>();
map.put("aa",new HelloWorld("1"));
map.put("vv",new HelloWorld("2"));
}
public HelloWorld getMap(String name) {
return map.get(name);
}
}
配置文件:实例工厂需要先实例化工厂
<bean id="factory" class="com.chenx.spring.beans.InstanceFactory"></bean>
<bean id="helloWorld" factory-bean="factory" factory-method="getMap">
<constructor-arg value="vv"></constructor-arg>
</bean>
5.FactoryBean配置
///摘抄
一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂Bean的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式。以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身。
//My
总之更加灵活
自定义FactoryBean步骤:
创建一个bean implements FactoryBean<> ,接着override 其中的三个方法,相当于配置bean:(getobject返回的实例)(getobjectType返回的类型)(isSingleton是否是单例)
package com.chenx.spring.beans;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean<HelloWorld> {
@Override
public HelloWorld getObject() throws Exception {
return new HelloWorld("1");
}
@Override
public Class<?> getObjectType() {
return HelloWorld.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
配置文件:(配置此后,其返回的是getobject中的返回值)
<bean id="helloWorld" class="com.chenx.spring.beans.MyFactoryBean"></bean>
还可以在自定义FactoryBean中加入属性,然后就可在配置文件中配置
6.基于注解的方式配置Bean
转载:!!
https://blog.csdn.net/u011266694/article/details/78918382