Spring的装配方式
参考资料
Spring - bean的autowire属性(自动装配)
Spring 自动装配
spring byType和byName 是什么意思
no
Spring中默认的方式,它不能进行自动装配,不采用autowire机制.,需要使用依赖注入,只能用<ref/>
标签,手动设置Bean的依赖关系。
<!--使用bean标签去申明bean-->
<bean id="waiter" class="com.fang.spring.Waiter" />
<!--可以保用p标签来注入依赖的bean-->
<bean id="store" class="com.fang.spring.Store">
<property name="waiter" ref="waiter"></property>
</bean>
<!-- 下面这种方式要使用p标签xmlns:p="http://www.springframework.org/schema/p" -->
<!--
<bean id="store" class="com.fang.spring.Store" p:waiter-ref="waiter" />
-->
byName和byType
这种两种方式都需要我们在Java类里设置setter方法,不同的是,byName是通过属性的名称(name或者id)自动装配(注入),Spring会在容器中查找名称与bean属性名称一致的bean,并自动注入到bean属性中。例如:beanA有一个属性eat,它的id设置为eat,那么它的setter方法要设置成setEat(E大小写都没事,不过还是要命名规范)。
这里有点小郁闷,很多人都说在beans标签加这个属性default-autowire=“byName”,但是老是通不过测试,beans标签不允许这个属性的设置,所以只能在bean标签设置了。
<bean id="waiter" class="com.fang.spring.Waiter" autowire="byName"/>
<bean id="store" class="com.fang.spring.Store" autowire="byName"/>
补充,在执行<bean id="waiter" class="com.fang.spring.Waiter" autowire="byName"/>
这一句的时候, Spring框架将Waiter这个实体类整个编译一下, 看看自己的这个类里面有几个属性(类型是实体类的属性, 不能是简单类型), 然后和ApplicationContext的配置文件一通对比, 如果有bean的id能跟自己的setter方法对上名字, 就把这个bean装载到自己的这个类里面。
byType则是通过类型自动装配(注入),Spring会在容器中查找类(Class)与bean属性类一致的bean,并自动注入到bean属性中,如果容器中包含多个这个类型的bean,Spring将抛出异常(就是不能存在多个bean的class指向同一个实体,而且都是byType类型注入的)。如果没有找到这个类型的bean,那么注入动作将不会执行。这样说可能很难理解,其实就是和setter方法中的参数类型有关。
<bean id="waiter" class="com.fang.spring.Waiter" autowire="byType"/>
<bean id="store" class="com.fang.spring.Store" autowire="byType"/>
<!--根据配置文件编译Store,里面有Waiter类型,配置文件里有com.fang.spring.Waiter,于是装载-->
public class Store {
@SuppressWarnings("unused")
private Waiter waiter;
public Store() {
System.out.println("士多店被初始化");
}
public void setWaiter(Waiter waiter) {
this.waiter = waiter;
System.out.println("设置士多店");
}
}
constructor
类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
假设Store有构造函数public Store(Waiter waiter),那么Spring会在容器中查找类型为Store的bean通过构造函数Store(Wai ter waiter)注入到A中。与byType一样,如果存在多个bean类型为Store,则会抛出异常,另外,如果在容器中找不到匹配的类型的bean,将抛出异常,因为Spring无法调用构造函数实例化这个bean。
<bean id="waiter" class="com.fang.spring.Waiter" autowire="byType"/>
<bean id="store" class="com.fang.spring.Store" >
<constructor-arg name="waiter" ref="waiter"></constructor-arg>
</bean>
//Store类的构造方法
public Store(Waiter waiter) {
System.out.println("士多店被初始化之构造方法");
}
autodetect
autodetect其实还是通过constructor或者byType实现的,如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
小结
自动装配没有自定义装配方式那么精确,而且不能自动装配简单属性(基本类型、字符串等),在使用时应注意。另一方面,自动装配功能和手动装配如果同时使用,那么自动装配就不起作用。
在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性。 然而, 若只希望装配个别属性时,autowi re 属性就不够灵活了.。autowire 属性要么根据类型自动装配,,要么根据名称自动装配,不能两者兼而有之。
Spring4.0新出了很多注解,通过注解的方式可以简化配置文件定义bean的方式,如通过@Configuration注解定义Bean。