对Spring IOC容器相关整理(二)
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" > <description>rabbitmq 连接服务配置</description> <!--步骤1、配置链接工厂--> <bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"> <property name="host" value="${mq.address}"/> <property name="port" value="${mq.port}"/> <property name="password" value="${mq.pwd}"/> <property name="username" value="${mq.user}"/> <property name="publisherConfirms" value="true"/> <property name="publisherReturns" value="true"/> <property name="virtualHost" value="${mq.vhost}"/> <property name="requestedHeartBeat" value="50"/> </bean> //....... </beans>
对于配置XML文件 Spring 提供了很多的元素和属性,用于对对象与其依赖关系进行描述。Spring的XML文件就像一张记录详细配料,火候等的菜谱。对于Spring XML文件,我们一般通过以<beans>....</beans>包围的元素开始配置。
有关http://www.springframework.org/schema/beans 中对于beans 的定义可参见:标签系列一:spring 中beans解释以及beans标签里面的属性
接下来我要整理一下关于beans 的相关的元素及属性:
beans命名空间下的元素
通过编辑器可以轻易的找到在beans命名空间下,存在beans、bean、alias、description、import 五个元素存在。(也可能是4个, 在http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 版中没有beans元素,4.0版存在(默认最新版请把上文中的-3.0 去掉))
1.1、beans元素
beans元素是顶层(通常为根)元素。允许定义所有嵌套bean定义的默认值。
beans元素有自己的属性:
1.1.1、default-autowire 属性:
default-autowire 有五个值 分别如下:
默认的值为:no 即不启用自动注入。
default:实际上是会优先执行constructor然后是byType
byType:这个是会根据类型去注入,当找到了会直接注入,没有找到不会报错,但是找到多个会报No unique bean of type的错误
byName:这个会根据name注入
constructor:这个是通过构造注入
no:不启用自动注入
1.1.2、default-autowire-candidates 属性:
default-autowire-candidates是候选者,自动装配时即匹配则被包含。不匹配的排除在外。
default-autowire-candidates属性的值允许使用模式字符串,例如我们制定default-autowire-candidates=“*abc”,则所有以“abc”结尾的Bean都将被自动装配。它还支持多个字符,可以通过,空格 等分割。
1.1.3、default-init-method 和 default-destroy-method 属性:
default-init-method="init" default-destroy-method="destroy"
很多Bean都需要配置初始化方法和销毁方法,那么可以在beans标签中配置default-init-method和default-destroy-method来指定所有Bean的默认初始化方法和销毁方法 (init 与 destroy 是bean中的方法)
1.1.4、default-lazy-init 属性:
spring配置默认default-lazy-init为false,当属性default-lazy-init设置成true时,sping不会再去加载整个对象实例图,大大减少了初始化的时间,减少了spring的启动时间。
1.1.5、default-merge 属性:
从Spring 2.0M2开始,beans支持default-merge= "true" 的定义,子类不需要重新定义父类的List型属性中已定义过的内容
1.1.6、profile 属性:
将程序从一个环境迁移或切换到另一个环境 定义环境名称。
默认上下文中,添加spring.profiles.default的配置,如下:
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>development</param-value>
</context-param>
而对于spring.profiles.default,这里需要说明下:在Spring的Profile中,Profile存在两种状态,一种为默认加载的profile(spring.profiles.default),一种为指定激活的profile(spring.profiles.active)。如果程序未指定active状态的profile,那么执行default状态的profile,如果两种状态都指定,则优先执行或选择active状态的profile。
1.2、alias 元素(别名)
在对bean进行定义时,除了使用id属性来指定名称之外,为了提供多个名称,可以使用alias标签来指定。而所有的这些名称都指向同一个bean,有时我们期望能在当前位置为那些在别处定义的bean引入别名。在XML配置文件中,可用单独的<alias/>元素来完成bean别名的定义。如:
配置文件中定义了一个JavaBean
<bean id="resourceHolder" class="com.zk.demo1025.ResourceHolder"> </bean>
我要给这个JavaBean增加别名,以方便不同对象来调用。我们就可以这样写:
<alias name="resourceHolder" alias="resourceHolder1"/>
<alias name="resourceHolder" alias="resourceHolder2"/>
<alias name="resourceHolder" alias="resourceHolder3"/>
或
<alias name="resourceHolder" alias="resourceHolder1,resourceHolder2,resourceHolder3"/>
或者是用name属性来指定,如:
<bean id="resourceHolder" name="resourceHolder1,resourceHolder2,resourceHolder3 " class="com.zk.demo1025.ResourceHolder"> </bean>
1.3、description (描述)元素
description元素必须在beans 中的第一行,用于描述配置的信息。
1.4 import 元素
在Spring的配置文件,有时候为了分模块的更加清晰的进行相关实体类的配置。引入其他模块XML
当使用import元素时会提供一下选项:
其中,以 .xml 结尾的是项目中的配置文件。
1.默认情况下,使用相对路径来辅助查找配置文件
2.Spring提供了四种前缀标记来辅助查找配置文件:
(1)[classpath:]:表示从classpath开始寻找后面的资源文件
(2)[file:]:表示使用文件系统的方式寻找后面的文件(文件的完整路径)
(3)[classpath*:]:表示不仅会在class路径中去查找文件,还会在jar中去查找文件
(4)[http:] :表示通过网络地址查找文件
注:classpath:XXXXX:相当于/WIN-INF/classes/xxxxx
1.5、bean 元素
bean元素的属性有很多:
常用属性有:
- id , id标签是bean的唯一标识,IoC容器中bean的id标签不能重复,否则报错。
- name ,name是bean的名称标识,IoC容器中bean的name标签不能重复 ,同一个bean中可以与id 重复(没有发现不良反应)
- class ,class属性是bean常用属性,为bean的全限定类名,指向classpath下类定义所在位置
- factory-method ,factory-method工厂方法属性,通过该属性,我们可以调用一个指定的静态工厂方法,创建bean实例
- factory-bean ,factory-bean就是生成bean的工厂对象,factory-bean属性和factory-method属性一起使用
- init-method ,init-method属性是bean的初始方法,在创建好bean后调用该方法
- destory-method ,destory-method属性是bean的销毁方法,在销毁bean之前调用该方法,一般在该方法中释放资源
- scope,scope属性表示bean的作用范围(参见:对Spring IOC容器相关整理(一))
- autowire ,autowire表示bean的自动装配
id标签的值 在 同一个配置文件中是惟一的,在多个spring文件中存在相同的id 或 name后面引入的配置会覆盖前面的bean
其余属性有:
- parent ,spring 中parent标签是指:某个<bean>的父类。这个类可以覆盖parent的属性
- abstract ,使用abstract 属性 定义公共的属性。bean使用abstract=true时,可以有class,也可以没有class,一般与parent 配合使用。
- autowire -candidate,值有 true, false、default 。autowire-candidate="false" 表示该对象不参与自动注入
- depends-on , depends-on适用于表面上看起来两个bean之间没有使用属性之类的强连接的bean,但是两个bean又确实存在前后依赖关系的情况,被depends-on链接的bean 先创建,后销毁,依赖他人的bean是先于被依赖bean销毁的
- lazy-init , 只有 true、false 用来指定bean是否在容器启动时初始化,为false时容器启动时初始化 用途: 通常用于解决spring循环引用的问题:
- primary ,primary的值有true和false两个可以选择。默认为false。当一个bean的primary设置为true,然后容器中有多个与该bean相同类型的其他bean,此时,当使用@Autowired想要注入一个这个类型的bean时,就不会因为容器中存在多个该类型的bean而出现异常。而是优先使用primary为true的bean。不过,如果容器中不仅有多个该类型的bean,而且这些bean中有多个的primary的值设置为true,那么使用byType注入还是会出错。
1.5.1、bean元素的子元素
由上图可以看到,bean元素中有7子元素
- property:通过setter对应的方法注入 。spring配置中property作为bean的属性。也就是指一个类中的成员。同时这个成员必须有set方法。
- description :描述,一个字符串,没什么好说的。
- constructor-arg :通过构造函数注入
- lookup-method :方法的覆盖。注入bean的作用域小于当前bean时,希望每次可以拿到最新的注入bean。
- meta:一个额外的属性,可以使用 BeanDefinition的getAttribute(key);方法获取,
- qualifier:当bean的注入项有多个实现时,使用Qualifier指定要注入的bean的标识
- replaced-method:方法的替换 ,要实现spring的MethodReplacer接口
- 下面对每个元素进行详细介绍:
a、property 设值注入
property 元素属性有 name、 ref 、value 三个。 其中 name 为类中要注入依赖项的名字。需要有set方法。name值与setXXX 中XXX一致,与声明的名字无关。
ref 为引用项bean的id 或name 。value 值为值类型
property 元素有以下子元素:
ref: <property name="....." ref="......" />就是找当前配置文件里的bean ,<ref bean ="....."/> 是寻找全局(可以到其他xml中)中的 bean;<ref>标签里 有3种属性 <ref bean="寻找全局(可以到其他xml中)中的 bean"/>,<ref local="关联当前xml的bean "/>,<ref parent="用于指定其依赖的父 JavaBean 定义"/>。在4.0BeanXSD中 ref 元素上的local 属性不再受支持
bean: 内部 Bean:当 Spring IoC 容器中的 bean1 只会被 bean2 引用,而不会被容器中任何其他 Bean 引用的时候,则可以将这个 bean1 以内部 Bean 的方式注入到 bean2 中。
description: 描述,一个字符串
value: 为属性注入字面值
set: 当属性为 java.util.Set 的时候 可以在集合上加 merge="true",允许与父类集合合并
<bean id="boss" class="***">
<property name="favorites">
<set>
<value>唱歌</value>
<value>运动</value>
<value>读书</value>
</set>
</property>
</bean>
array:当属性为 java.util.Array 的时候 可以在集合上加 merge="true",允许与父类集合合并
<property name="favs"> <array> <value>足球</value> <value>篮球</value> <value>排球</value> </array> </property>
idref: idref元素只是一种防止错误的方法,可以将容器中另一个bean的id(一个字符串值,而不是引用)传递给一个<constructor-arg/>或<property/>元素(在某种意义上等同于<value/>)
<bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <idref bean="theTargetBean"/> </property> </bean>
list: 当属性为 java.util.List 的时候,可以在集合上加 merge="true",允许与父类集合合并
<bean id="boss" class="***">
<property name="favorites">
<list>
<value>唱歌</value>
<value>运动</value>
<value>读书</value>
</list>
</property>
</bean>
map: 当属性为 java.util.Map 的时候 可以在集合上加 merge="true",允许与父类集合合并
<bean id="boss" class="***">
<property name="favorites">
<map>
<entry>
<key><value>key01</value></key>
<value>唱歌</value>
</entry>
<entry>
<key><value>key02</value></key>
<value>运动</value>
</entry>
<entry>
<key><ref bean="keyBean" /></key>
<ref bean="valueBean" />
</entry>
</map>
</property>
</bean>
meta: 一个额外的属性,可以使用 BeanDefinition的getAttribute(key);方法获取,
<meta key = "key" value = "values">
null: 需要为某个 bean 的属性注入一个 null 值,在这里我们需要使用专用的 <null/> 元素标签,通过它可以为其他对象的属性注入 null 值。
props: 当属性为 java.util.Properties 的时候 可以在集合上加 merge="true",允许与父类集合合并
<bean id="boss" class="***">
<property name="favorites">
<props>
<prop key="p01">唱歌</prop>
<prop key="p02">运动</prop>
<prop key="p03">读书</prop>
</props>
</properties>
</property>
</bean>
b、constructor-arg 构造注入
如下图,constructor-arg 有如下属性:
- value :注入的字面值
- ref:注入对其他bean的引用
- name:注入项的名称
- index:注入项在参数列表的序列号(从0开始)
- type:注入项的类型
constructor-arg下的子元素如下:
与 property 属性相同,不在赘述。
c、lookup-method 方法注入
可以不是 抽象类型的方法
public abstract class FathorCarService { public void read(){ CarService carService=look(); System.out.println("睡觉,吃法,上班"); carService.read(); } protected abstract CarService look(); } public class CarService { public void read(){ System.out.println("读书,看报,写字"); } } public static void main(String[] args) { ClassPathXmlApplicationContext cx=new ClassPathXmlApplicationContext("classpath:spring/spring-config.xml"); FathorCarService carService=(FathorCarService)cx.getBean("car2"); carService.read(); } <bean id="car" class="service.CarService" scope="prototype"/> <bean id="car2" class="service.FathorCarService"> <lookup-method name="look" bean="car"/> </bean>
如:
protected CarService look(){ return null; }
同样可以进行方法注入。结果如下:
官方文档中 注入方法签名:
- public|protected要求方法必须是可以被子类重写和调用的;
- abstract可选,如果是抽象方法,CGLIB的动态代理类就会实现这个方法,如果不是抽象方法,就会覆盖这个方法,所以没什么影响;
- return-type就是non-singleton-bean的类型咯,当然可以是它的父类或者接口。
- no-arguments不允许有参数。
d、replaced-method 方法替换
public class FathorCarService { public void read(){ CarService carService=look(); System.out.println("睡觉,吃法,上班"); carService.read(); } protected CarService look(){ return null; } } public class CarService implements MethodReplacer { public void read(){ System.out.println("读书,看报,写字"); } @Override public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { System.out.println("遛狗,跳绳,跑路"); return null; } } public static void main(String[] args) { ClassPathXmlApplicationContext cx=new ClassPathXmlApplicationContext("classpath:spring/spring-config.xml"); FathorCarService carService=(FathorCarService)cx.getBean("car2"); carService.read(); } <bean id="car" class="service.CarService" scope="prototype"/> <bean id="car2" class="service.FathorCarService"> <replaced-method name="read" replacer="car"/> </bean>
使用方法替换将本应该输出
输出为:
大概就这么多了,如果有什么疏漏的地方,望各位博友指出.....