关于Spring的自动装配问题
2016-11-27 13:48
323 查看
自动装配: Spring IoC 容器提供了对相互协作的Bean进行自动装配的功能。可以自动让Spring通过检查容器中的内容,来替开发人员指定Bean的依赖关系。由于autowire 可以针对单个Bean设置,因此可以让有些Bean使用autowire,有些Bean不使用。autowire的方便之处在于减少或消除对属性或构造器参数的设置,从而简化配置文件。
autowire的五种类型:
1、no :默认值,表明不使用自动装配。可以通过元素显示指定依赖,显示指定可以使配置更灵活、更清晰。
2、byName :根据属性名自动装配。此项将检查容器并查找id 值与属性名完全一致的Bean,将该Bean与属性自动装配。
byName示例:
Film类有如下属性:
Koko类:
Lolo类:
配置文件(ApplicationContext.xml):
main方法测试:
Console输出
:
修改配置文件:
再次运行Console结果
3、byType: 如果容器中存在一个与指定属性类型相同的Bean,那么将对该属性自动装配。如果存在多个该类型的Bean,那么将会抛出异常(NoUniqueDefinitionException),若没有找到相匹配的Bean,不会抛出异常,也不会对属性进行设置,此时可以通过设置dependency-check=”objects”让spring抛出异常。
byType示例:
Film类:
配置文件:
Console
存在多个与该属性类型相同的Bean时:
修改配置文件:容器中存在两个Lolo类型的Bean
Console
不存在与该属性类型相同的Bean时:
修改配置文件:容器中不存在Lolo类型的Bean
console:
4、constructor: 与byType的方式类似,不同之处在于它应用于构造器的参数,根据构造器的参数类型进行自动装配。如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。
(1)Film构造器参数的数量与属性的数量相同
Spring根据Film构造器每个参数的类型,在容器中匹配,对film Bean进行装配
console:
(2)Film构造器参数的数量比属性的数量少
console:
构造器参数中没有ko属性,spring没有对这个属性进行装配
(3)只有默认的构造器时:
console:
至于原因嘛,自己猜!
(4)一次蛋疼的纯属娱乐的测试
console:
film的lo属性没有装配,ko属性装配了
我们修改Film的那几个构造器的顺序
再看结果
:
film的Ko属性没有被装配,lo属性装配了
后续的构造器中参数对应的属性被装配了,前面的没有被装配,是不是很有意思
(5)回到第(1)种情形,但容器中有多个相同类型的Bean
console
第二个异常:
继续测试,取消默认构造方法的注释
console:
个人理解为按照第一个构造方法的参数匹配行不通,就使用默认的构造方法进行constructor自动装配,两个属性就全变成了null(这只是个人的理解,还请大神指点迷津)
(6)容器中不存在构造器参数中某一类型的Bean时
Console:
第二个异常:
因为我们用的ApplicationContext接口,在初始化应用上下文时会实例化所有singleton Bean,而film设置了custructor自动装配,容器中缺少Lolo类型的bean ,也就报出了异常(4、constructor: 与byType的方式类似,不同之处在于它应用于构造器的参数,根据构造器的参数类型进行自动装配。如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。)
继续测试,取消Film类默认构造方法的注释
console:
没有抛出异常,两个属性值全为null,估计也是参照了默认的构造方法进行自动装配
5、autodetect: 通过Bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现类中有默认的构造器,那么将使用byType方式。
autodetect示例:
类中没有默认的构造器时
console:
类中存在默认构造器时
console:
结语:感谢您阅读,以上纯属个人学习理解,毕竟水平有限,如有错误,还请您指点迷津!
autowire的五种类型:
1、no :默认值,表明不使用自动装配。可以通过元素显示指定依赖,显示指定可以使配置更灵活、更清晰。
2、byName :根据属性名自动装配。此项将检查容器并查找id 值与属性名完全一致的Bean,将该Bean与属性自动装配。
byName示例:
Film类有如下属性:
public class Film { private Lolo lo; private Koko ko; public Film() { super(); // TODO Auto-generated constructor stub } ----此后均省略setter,getter---- }
Koko类:
public class Koko { private String name; public Koko() { super(); // TODO Auto-generated constructor stub }
Lolo类:
public class Lolo { private String name; public Lolo() { super(); // TODO Auto-generated constructor stub } }
配置文件(ApplicationContext.xml):
<beans> <bean id="ko" class="com.po 4000 jo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="byName"> </bean> </beans>
main方法测试:
public static void main(String[] args) { ApplicationContext actx= new ClassPathXmlApplicationContext("ApplicationContext.xml"); System.out.println("-----------------"); Film film1= (Film) actx.getBean("film"); System.out.println(film1.getKo().getName()); System.out.println(film1.getLo().getName()); System.out.println("-----------------"); }
Console输出
:
修改配置文件:
<beans> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="byName"> </bean> </beans>
再次运行Console结果
3、byType: 如果容器中存在一个与指定属性类型相同的Bean,那么将对该属性自动装配。如果存在多个该类型的Bean,那么将会抛出异常(NoUniqueDefinitionException),若没有找到相匹配的Bean,不会抛出异常,也不会对属性进行设置,此时可以通过设置dependency-check=”objects”让spring抛出异常。
byType示例:
Film类:
public class Film { private Lolo lo; private Koko ko; public Film() { super(); // TODO Auto-generated constructor stub } }
配置文件:
<beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="byType"> </bean> </beans>
Console
存在多个与该属性类型相同的Bean时:
修改配置文件:容器中存在两个Lolo类型的Bean
<beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo1" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="lo2" class="com.pojo.Lolo"> <property name="name" value="怪怪"/> </bean> <bean id="film" class="com.pojo.Film" autowire="byType"> </bean> </beans>
Console
不存在与该属性类型相同的Bean时:
修改配置文件:容器中不存在Lolo类型的Bean
<beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="film" class="com.pojo.Film" autowire="byType"> </bean> </beans>
console:
4、constructor: 与byType的方式类似,不同之处在于它应用于构造器的参数,根据构造器的参数类型进行自动装配。如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。
(1)Film构造器参数的数量与属性的数量相同
public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; } public Film() { super(); // TODO Auto-generated constructor stub } } 配置文件: <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="constructor"> </bean> </beans>
Spring根据Film构造器每个参数的类型,在容器中匹配,对film Bean进行装配
console:
(2)Film构造器参数的数量比属性的数量少
public class Film { private Lolo lo; private Koko ko; //构造器中只有lo属性 public Film(Lolo lo) { super(); this.lo = lo; } public Film() { super(); } } 配置文件: <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="constructor"> </bean> </beans>
console:
构造器参数中没有ko属性,spring没有对这个属性进行装配
(3)只有默认的构造器时:
public class Film { private Lolo lo; private Koko ko; public Film() { super(); } } 配置文件: <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="constructor"> </bean> </beans>
console:
至于原因嘛,自己猜!
(4)一次蛋疼的纯属娱乐的测试
public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo) { super(); this.lo = lo; } public Film(Koko ko) { super(); this.ko = ko; } public Film() { super(); } } 配置文件 <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="constructor"> </bean> </beans>
console:
film的lo属性没有装配,ko属性装配了
我们修改Film的那几个构造器的顺序
public class Film { private Lolo lo; private Koko ko; //改变一下顺序 public Film(Koko ko) { super(); this.ko = ko; } public Film(Lolo lo) { super(); this.lo = lo; } public Film() { super(); } } 配置文件不变
再看结果
:
film的Ko属性没有被装配,lo属性装配了
后续的构造器中参数对应的属性被装配了,前面的没有被装配,是不是很有意思
(5)回到第(1)种情形,但容器中有多个相同类型的Bean
//注释掉默认的构造方法 public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; } /** public Film() { super(); } */ } 配置文件进行修改,容器中有多个Lolo类型的Bean <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo1" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="lo2" class="com.pojo.Lolo"> <property name="name" value="怪怪"/> </bean> <bean id="film" class="com.pojo.Film" autowire="constructor"> </bean> </beans>
console
第二个异常:
继续测试,取消默认构造方法的注释
public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; } public Film() { super(); // TODO Auto-generated constructor stub } 配置文件不变
console:
个人理解为按照第一个构造方法的参数匹配行不通,就使用默认的构造方法进行constructor自动装配,两个属性就全变成了null(这只是个人的理解,还请大神指点迷津)
(6)容器中不存在构造器参数中某一类型的Bean时
//注释掉默认构造方法 public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; } /** public Film() { super(); } */ } 修改配置文件:删除Lolo类型的Bean <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="film" class="com.pojo.Film" autowire="constructor"> </bean> </beans>
Console:
第二个异常:
因为我们用的ApplicationContext接口,在初始化应用上下文时会实例化所有singleton Bean,而film设置了custructor自动装配,容器中缺少Lolo类型的bean ,也就报出了异常(4、constructor: 与byType的方式类似,不同之处在于它应用于构造器的参数,根据构造器的参数类型进行自动装配。如果在容器中没有找到与构造器参数类型一致的Bean,那么将会抛出异常。)
继续测试,取消Film类默认构造方法的注释
public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; } public Film() { super(); // TODO Auto-generated constructor stub } } 配置文件不变
console:
没有抛出异常,两个属性值全为null,估计也是参照了默认的构造方法进行自动装配
5、autodetect: 通过Bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现类中有默认的构造器,那么将使用byType方式。
autodetect示例:
类中没有默认的构造器时
//注释默认的构造器 public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; System.out.println("使用了constructor"); } /** public Film() { super(); System.out.println("使用了byType"); } */ } 配置文件: <beans> <bean id="ko" class="com.pojo.Koko"> <property name="name" value="蛇蛇"/> </bean> <bean id="lo" class="com.pojo.Lolo"> <property name="name" value="皮皮"/> </bean> <bean id="film" class="com.pojo.Film" autowire="autodetect"> </bean> </beans>
console:
类中存在默认构造器时
//取消默认构造器的注释 public class Film { private Lolo lo; private Koko ko; public Film(Lolo lo, Koko ko) { super(); this.lo = lo; this.ko = ko; System.out.println("使用了constructor"); } public Film() { super(); System.out.println("使用了byType"); // TODO Auto-generated constructor stub } } 配置文件不变
console:
结语:感谢您阅读,以上纯属个人学习理解,毕竟水平有限,如有错误,还请您指点迷津!
相关文章推荐
- 关于Struts在Spring中使用autowired 自动注入的问题
- spring quartz 与自动装配 产生的问题
- 关于Spring整合Hibernate中自动建表问题(hbm2ddl.auto)
- mybatis-spring无法自动装配mapper的问题
- 关于spring boot无法自动注入bean问题解决方案
- 关于spring和springmvc的xml自动扫描配置问题
- struts2与spring集成时,关于class属性及成员bean自动注入的问题
- 关于非Spring管理下的Bean通过反射在newInstance()下的自动注入问题
- 关于SpringBoot bean无法注入的问题(与文件包位置有关)改变自动扫描的包
- 关于SpringBoot bean无法注入的问题(与文件包位置有关)改变自动扫描的包
- 关于Struts在Spring中使用autowired 自动注入的问题
- struts2与spring集成时,关于Action类中成员bean自动注入的问题
- struts2与spring集成时,关于Action类中成员bean自动注入的问题
- 关于SpringBoot404, bean无法注入的问题(与文件包位置有关)改变自动扫描的包
- 关于Spring基于构造子自动装配的一点探讨
- struts2与spring集成时,关于class属性及成员bean自动注入的问题
- struts2与spring集成时,关于Action类中成员bean自动注入的问题
- 关于Castle IOC容器自动装配的问题
- Spring《四-一》解决自动装配的问题
- 关于Spring中为静态static的@Resource自动注入失败的问题