全文目录:Spring概述IOC理论推导快速上手Spring依赖注入(DI)自动装配1。Spring概述1。1简介Spring:春天给软件行业带来了春天2002年,RodJahnson首次推出了Spring框架雏形interface21框架。2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1。0正式版。很难想象RodJohnson的学历,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。Spring理念:使现有技术更加实用。本身就是一个大杂烩,整合现有的框架技术官网:http:spring。io官方下载地址:https:repo。spring。iolibsreleaselocalorgspringframeworkspringGitHub:https:github。comspringprojects1。2优点1、Spring是一个开源免费的框架,容器。2、Spring是一个轻量级的框架,非侵入式的。3、控制反转IoC,面向切面Aop4、对事物的支持,对框架的支持 一句话概括:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。1。3组成 Spring框架是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理bean的方式。组成Spring框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:核心容器:核心容器提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。Spring上下文:Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。SpringAOP:通过配置管理特性,SpringAOP模块直接将面向切面的编程功能,集成到了Spring框架中。所以,可以很容易地使Spring框架管理任何支持AOP的对象。SpringAOP模块为基于Spring的应用程序中的对象提供了事务管理服务。通过使用SpringAOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。SpringDAO:JDBCDAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。SpringDAO的面向JDBC的异常遵从通用的DAO异常层次结构。SpringORM:Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO、Hibernate和iBatisSQLMap。所有这些都遵从Spring的通用事务和DAO异常层次结构。SpringWeb模块:Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。所以,Spring框架支持与JakartaStruts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。SpringMVC框架:MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。1。4拓展SpringBoot与SpringCloud SpringBoot是Spring的一套快速配置脚手架,可以基于SpringBoot快速开发单个微服务;SpringCloud是基于SpringBoot实现的;SpringBoot专注于快速、方便集成的单个微服务个体,SpringCloud关注全局的服务治理框架;SpringBoot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,SpringCloud很大的一部分是基于SpringBoot来实现,SpringBoot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开SpringBoot,属于依赖的关系。SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。2。IOC理论推导2。1IoC基础 分析实现,我们先用我们原来的方式写一段代码: 1、先写一个UserDao接口publicinterfaceUserDao{publicvoidgetUser();} 2、再去写Dao的实现类publicclassUserDaoImplimplementsUserDao{OverridepublicvoidgetUser(){System。out。println(获取用户数据);} 3、然后去写UserService的接口publicinterfaceUserService{publicvoidgetUser();} 4、最后写Service的实现类publicclassUserServiceImplimplementsUserService{privateUserDaouserDaonewUserDaoImpl();OverridepublicvoidgetUser(){userDao。getUser();}} 5、测试一下Testpublicvoidtest(){UserServiceservicenewUserServiceImpl();service。getUser();} 这是我们原来的方式,开始大家也都是这么去写的对吧。那我们现在修改一下 把Userdao的实现类增加一个publicclassUserDaoMySqlImplimplementsUserDao{OverridepublicvoidgetUser(){System。out。println(MySql获取用户数据);}} 紧接着我们要去使用MySql的话,我们就需要去service实现类里面修改对应的实现publicclassUserServiceImplimplementsUserService{privateUserDaouserDaonewUserDaoMySqlImpl();OverridepublicvoidgetUser(){userDao。getUser();}} 在假设,我们再增加一个Userdao的实现类。publicclassUserDaoOracleImplimplementsUserDao{OverridepublicvoidgetUser(){System。out。println(Oracle获取用户数据);}} 那么我们要使用Oracle,又需要去service实现类里面修改对应的实现。假设我们的这种需求非常大,这种方式就根本不适用了,甚至反人类对吧,每次变动,都需要修改大量代码。这种设计的耦合性太高了,牵一发而动全身。 那我们如何去解决呢? 我们可以在需要用到他的地方,不去实现它,而是留出一个接口,利用set,我们去代码里修改下publicclassUserServiceImplimplementsUserService{privateUserDaouserDao;利用set实现publicvoidsetUserDao(UserDaouserDao){this。userDaouserDao;}OverridepublicvoidgetUser(){userDao。getUser();}} 现在去我们的测试类里,进行测试;Testpublicvoidtest(){UserServiceImplservicenewUserServiceImpl();service。setUserDao(newUserDaoMySqlImpl());service。getUser();那我们现在又想用Oracle去实现呢service。setUserDao(newUserDaoOracleImpl());service。getUser();} 大家发现了区别没有?可能很多人说没啥区别。但是同学们,他们已经发生了根本性的变化,很多地方都不一样了。仔细去思考一下,以前所有东西都是由程序去进行控制创建,而现在是由我们自行控制创建对象,把主动权交给了调用者。程序不用去管怎么创建,怎么实现了。它只负责提供一个接口。 这种思想,从本质上解决了问题,我们程序员不再去管理对象的创建了,更多的去关注业务的实现。耦合性大大降低。这也就是IOC的原型!2。2IOC本质控制反转IoC(InversionofControl),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。 IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(DependencyInjection,DI)。3。快速上手Spring3。1HelloSpring (1)导入Jar包 注:spring需要导入commonslogging进行日志记录。我们利用maven,他会自动下载对应的依赖项。dependencygroupIdorg。springframeworkgroupIdspringwebmvcartifactIdversion5。1。10。RELEASEversiondependency (2)编写代码 1、编写一个Hello实体类publicclassHello{privateStringname;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this。namename;}publicvoidshow(){System。out。println(Hello,name);}} 2、编写我们的spring文件,这里我们命名为beans。xmllt;?xmlversion1。0encodingUTF8?beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsd!bean就是java对象,由Spring创建和管理beanidhelloclasscom。kuang。pojo。HellopropertynamenamevalueSpringbeanbeans 3、我们可以去进行测试了。Testpublicvoidtest(){解析beans。xml文件,生成管理相应的Bean对象ApplicationContextcontextnewClassPathXmlApplicationContext(beans。xml);getBean:参数即为spring配置文件中bean的id。Hellohello(Hello)context。getBean(hello);hello。show();}思考Hello对象是谁创建的?hello对象是由Spring创建的Hello对象的属性是怎么设置的?hello对象的属性是由Spring容器设置的这个过程就叫控制反转:控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的反转:程序本身不创建对象,而变成被动的接收对象依赖注入:就是利用set方法来进行注入的IOC是一种编程思想,由主动的编程变成被动的接收 修改案例一我们在案例一中,新增一个Spring配置文件beans。xmllt;?xmlversion1。0encodingUTF8?beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsdbeanidMysqlImplclasscom。kuang。dao。impl。UserDaoMySqlImplbeanidOracleImplclasscom。kuang。dao。impl。UserDaoOracleImplbeanidServiceImplclasscom。kuang。service。impl。UserServiceImpl!注意:这里的name并不是属性,而是set方法后面的那部分,首字母小写!引用另外一个bean,不是用value而是用refpropertynameuserDaorefOracleImplbeanbeans测试!Testpublicvoidtest2(){ApplicationContextcontextnewClassPathXmlApplicationContext(beans。xml);UserServiceImplserviceImpl(UserServiceImpl)context。getBean(ServiceImpl);serviceImpl。getUser();}OK,到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的IoC,一句话搞定:对象由Spring来创建,管理,装配!3。2IOC创建对象方式 通过无参构造方法来创建 1、User。javapublicclassUser{privateStringname;publicUser(){System。out。println(user无参构造方法);}publicvoidsetName(Stringname){this。namename;}publicvoidshow(){System。out。println(namename);}} 2、beans。xmllt;?xmlversion1。0encodingUTF8?beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsdbeaniduserclasscom。kuang。pojo。Userpropertynamenamevaluekuangshenbeanbeans 3、测试类Testpublicvoidtest(){ApplicationContextcontextnewClassPathXmlApplicationContext(beans。xml);在执行getBean的时候,user已经创建好了,通过无参构造Useruser(User)context。getBean(user);调用对象的方法。user。show();} 结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了! 通过有参构造方法来创建 1、UserT。javapublicclassUserT{privateStringname;publicUserT(Stringname){this。namename;}publicvoidsetName(Stringname){this。namename;}publicvoidshow(){System。out。println(namename);}} 2、beans。xml有三种方式编写!第一种根据index参数下标设置beaniduserTclasscom。kuang。pojo。UserT!index指构造方法,下标从0开始constructorargindex0valuekuangshen2bean!第二种根据参数名字设置beaniduserTclasscom。kuang。pojo。UserT!name指参数名constructorargnamenamevaluekuangshen2bean!第三种根据参数类型设置beaniduserTclasscom。kuang。pojo。UserTconstructorargtypejava。lang。Stringvaluekuangshen2bean 3、测试TestpublicvoidtestT(){ApplicationContextcontextnewClassPathXmlApplicationContext(beans。xml);UserTuser(UserT)context。getBean(userT);user。show();} 结论:在配置文件加载的时候。其中管理的对象都已经初始化了!3。3Spring配置 (1)别名 alias设置别名,为bean设置别名,可以设置多个别名!设置别名:在获取Bean的时候可以使用别名获取 (2)Bean的配置!bean就是java对象,由Spring创建和管理!id是bean的标识符,要唯一,如果没有配置id,name就是默认标识符如果配置id,又配置了name,那么name是别名name可以设置多个别名,可以用逗号,分号,空格隔开如果不配置id和name,可以根据applicationContext。getBean(。class)获取对象;class是bean的全限定名包名类名beanidhellonamehello2h2,h3;h4classcom。kuang。pojo。HellopropertynamenamevalueSpringbean (3)import 团队的合作通过import来实现。importresource{path}beans。xml4。依赖注入(DI)4。1概念依赖注入(DependencyInjection,DI)。依赖:指Bean对象的创建依赖于容器。Bean对象的依赖资源。注入:指Bean对象所依赖的资源,由容器来设置和装配。4。2构造器注入 我们在之前的案例已经讲过了4。3Set注入 要求被注入的属性,必须有set方法,set方法的方法名由set属性首字母大写,如果属性是boolean类型,没有set方法,是is。 测试pojo类: Address。javapublicclassAddress{privateStringaddress;publicStringgetAddress(){returnaddress;}publicvoidsetAddress(Stringaddress){this。addressaddress;}} Student。javapackagecom。kuang。pojo;importjava。util。List;importjava。util。Map;importjava。util。Properties;importjava。util。Set;publicclassStudent{privateStringname;privateAddressaddress;privateString〔〕books;privateListStringhobbys;privateMapString,Stringcard;privateSetStringgames;privateStringwife;privatePropertiesinfo;publicvoidsetName(Stringname){this。namename;}publicvoidsetAddress(Addressaddress){this。addressaddress;}publicvoidsetBooks(String〔〕books){this。booksbooks;}publicvoidsetHobbys(ListStringhobbys){this。hobbyshobbys;}publicvoidsetCard(MapString,Stringcard){this。cardcard;}publicvoidsetGames(SetStringgames){this。gamesgames;}publicvoidsetWife(Stringwife){this。wifewife;}publicvoidsetInfo(Propertiesinfo){this。infoinfo;}publicvoidshow(){System。out。println(namename,addressaddress。getAddress(),books);for(Stringbook:books){System。out。print(book);}System。out。println(爱好:hobbys);System。out。println(card:card);System。out。println(games:games);System。out。println(wife:wife);System。out。println(info:info);}}4。3。1常量注入beanidstudentclasscom。kuang。pojo。Studentpropertynamenamevalue小明bean 测试:Testpublicvoidtest01(){ApplicationContextcontextnewClassPathXmlApplicationContext(applicationContext。xml);Studentstudent(Student)context。getBean(student);System。out。println(student。getName());}4。3。2Bean注入 注意点:这里的值是一个引用,refbeanidaddrclasscom。kuang。pojo。Addresspropertynameaddressvalue重庆beanbeanidstudentclasscom。kuang。pojo。Studentpropertynamenamevalue小明propertynameaddressrefaddrbean4。3。3数组注入beanidstudentclasscom。kuang。pojo。Studentpropertynamenamevalue小明propertynameaddressrefaddrpropertynamebooksvalue西游记valuevalue红楼梦valuevalue水浒传valuearraypropertybean4。4。4List注入propertynamehobbyslistvalue听歌valuevalue看电影valuevalue爬山valuelistproperty4。4。5Map注入propertynamecardmapentrykey中国邮政value456456456465456entrykey建设value1456682255511mapproperty4。4。6set注入propertynamegamessetvalueLOLvaluevalueBOBvaluevalueCOCvaluesetproperty4。4。7Null注入propertynamewifenullproperty4。4。8Properties注入propertynameinfopropspropkey学号20190604proppropkey性别男proppropkey姓名小明proppropsproperty 测试结果:4。4p命名和c命名注入 User。java:【注意:这里没有有参构造器!】publicclassUser{privateStringname;privateintage;publicvoidsetName(Stringname){this。namename;}publicvoidsetAge(intage){this。ageage;}OverridepublicStringtoString(){returnUser{namename,ageage};}}4。1P命名空间注入 需要在头文件中加入约束文件导入约束:xmlns:phttp:www。springframework。orgschemap!P(属性:properties)命名空间,属性依然要设置set方法beaniduserclasscom。kuang。pojo。Userp:name狂神p:age184。2c命名空间注入 需要在头文件中加入约束文件导入约束:xmlns:chttp:www。springframework。orgschemac!C(构造:Constructor)命名空间,属性依然要设置set方法beaniduserclasscom。kuang。pojo。Userc:name狂神c:age18 发现问题:爆红了,刚才我们没有写有参构造! 解决:把有参构造器加上,这里也能知道,c就是所谓的构造器注入! 测试代码:Testpublicvoidtest02(){ApplicationContextcontextnewClassPathXmlApplicationContext(applicationContext。xml);Useruser(User)context。getBean(user);System。out。println(user);}4。5Bean的作用域 在Spring中,那些组成应用程序的主体及由SpringIoC容器所管理的对象,被称之为bean。简单地讲,bean就是由IoC容器初始化、装配及管理的对象。 几种作用域中,request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的SpringApplicationContext环境。4。5。1Singleton 当一个bean的作用域为Singleton,那么SpringIoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:beanidServiceImplclasscn。csdn。service。ServiceImplscopesingleton 测试:Testpublicvoidtest03(){ApplicationContextcontextnewClassPathXmlApplicationContext(applicationContext。xml);Useruser(User)context。getBean(user);Useruser2(User)context。getBean(user);System。out。println(useruser2);}4。5。2Prototype 当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将bean定义成prototype,可以这样配置:beanidaccountclasscom。foo。DefaultAccountscopeprototype或者beanidaccountclasscom。foo。DefaultAccountsingletonfalse4。5。3Request 当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的SpringApplicationContext情形下有效。考虑下面bean定义:beanidloginActionclasscn。csdn。LoginActionscoperequest 针对每次HTTP请求,Spring容器会根据loginActionbean的定义创建一个全新的LoginActionbean实例,且该loginActionbean实例仅在当前HTTPrequest内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginActionbean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。4。5。4Session 当一个bean的作用域为Session,表示在一个HTTPSession中,一个bean定义对应一个实例。该作用域仅在基于web的SpringApplicationContext情形下有效。考虑下面bean定义:beaniduserPreferencesclasscom。foo。UserPreferencesscopesession 针对某个HTTPSession,Spring容器会根据userPreferencesbean定义创建一个全新的userPreferencesbean实例,且该userPreferencesbean仅在当前HTTPSession内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTPSession中根据userPreferences创建的实例,将不会看到这些特定于某个HTTPSession的状态变化。当HTTPSession最终被废弃的时候,在该HTTPSession作用域内的bean也会被废弃掉5。自动装配5。1Bean的自动装配 推荐不使用自动装配xml配置,而使用注解 测试环境搭建 1、新建一个项目 2、新建两个实体类,CatDog都有一个叫的方法publicclassCat{publicvoidshout(){System。out。println(miao);}}publicclassDog{publicvoidshout(){System。out。println(wang);}} 3、新建一个用户类UserpublicclassUser{privateCatcat;privateDogdog;privateStringstr;} 4、编写Spring配置文件lt;?xmlversion1。0encodingUTF8?beansxmlnshttp:www。springframework。orgschemabeansxmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:www。springframework。orgschemabeanshttp:www。springframework。orgschemabeansspringbeans。xsdbeaniddogclasscom。kuang。pojo。Dogbeanidcatclasscom。kuang。pojo。Catbeaniduserclasscom。kuang。pojo。Userpropertynamecatrefcatpropertynamedogrefdogpropertynamestrvalueqinjiangbeanbeans 5、测试publicclassMyTest{TestpublicvoidtestMethodAutowire(){ApplicationContextcontextnewClassPathXmlApplicationContext(beans。xml);Useruser(User)context。getBean(user);user。getCat()。shout();user。getDog()。shout();}} 结果正常输出,环境OK5。1。1byName autowirebyName(按名称自动装配) 由于在手动配置xml过程中,常常发生字母缺漏和大小写等错误,而无法对其进行检查,使得开发效率降低。 采用自动装配将避免这些错误,并且使配置简单化。 测试: 1、修改bean配置,增加一个属性autowirebyNamebeaniduserclasscom。kuang。pojo。UserautowirebyNamepropertynamestrvalueqinjiangbean 2、再次测试,结果依旧成功输出! 3、我们将cat的beanid修改为catXXX 4、再次测试,执行时报空指针java。lang。NullPointerException。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。 小结: 当一个bean节点带有autowirebyName的属性时。将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。去spring容器中寻找是否有此字符串名称id的对象。如果有,就取出注入;如果没有,就报空指针异常。5。1。2byType autowirebyType(按类型自动装配) 使用autowirebyType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。NoUniqueBeanDefinitionException 测试: 1、将user的bean配置修改一下:autowirebyType 2、测试,正常输出 3、在注册一个cat的bean对象!beaniddogclasscom。kuang。pojo。Dogbeanidcatclasscom。kuang。pojo。Catbeanidcat2classcom。kuang。pojo。Catbeaniduserclasscom。kuang。pojo。UserautowirebyTypepropertynamestrvalueqinjiangbean 4、测试,报错:NoUniqueBeanDefinitionException 5、删掉cat2,将cat的bean名称改掉!测试!因为是按类型装配,所以并不会报异常,也不影响最后的结果。甚至将id属性去掉,也不影响结果。 这就是按照类型自动装配!5。2使用注解 jdk1。5开始支持注解,spring2。5开始全面支持注解。 准备工作:利用注解的方式注入属性。 1、在spring配置文件中引入context文件头xmlns:contexthttp:www。springframework。orgschemacontexthttp:www。springframework。orgschemacontexthttp:www。springframework。orgschemacontextspringcontext。xsd2、开启属性注解支持! 2、开启属性注解支持!AutowiredAutowired是按类型自动转配的,不支持id匹配。需要导入springaop的包! 测试: 1、将User类中的set方法去掉,使用Autowired注解publicclassUser{AutowiredprivateCatcat;AutowiredprivateDogdog;privateStringstr;publicCatgetCat(){returncat;}publicDoggetDog(){returndog;}publicStringgetStr(){returnstr;}} 2、此时配置文件内容context:annotationconfigbeaniddogclasscom。kuang。pojo。Dogbeanidcatclasscom。kuang。pojo。Catbeaniduserclasscom。kuang。pojo。User 3、测试,成功输出结果! Autowired(requiredfalse)说明:false,对象可以为null;true,对象必须存对象,不能为null。如果允许对象为null,设置requiredfalse,默认为trueAutowired(requiredfalse)privateCatcat;QualifierAutowired是根据类型自动装配的,加上Qualifier则可以根据byName的方式自动装配Qualifier不能单独使用。 测试实验步骤: 1、配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!beaniddog1classcom。kuang。pojo。Dogbeaniddog2classcom。kuang。pojo。Dogbeanidcat1classcom。kuang。pojo。Catbeanidcat2classcom。kuang。pojo。Cat 2、没有加Qualifier测试,直接报错 3、在属性上添加Qualifier注解AutowiredQualifier(valuecat2)privateCatcat;AutowiredQualifier(valuedog2)privateDogdog; 测试,成功输出!ResourceResource如有指定的name属性,先按该属性进行byName方式查找装配;其次再进行默认的byName方式进行装配;如果以上都不成功,则按byType的方式自动装配。都不成功,则报异常。 实体类:publicclassUser{如果允许对象为null,设置requiredfalse,默认为trueResource(namecat2)privateCatcat;ResourceprivateDogdog;privateStringstr;} beans。xmlbeaniddogclasscom。kuang。pojo。Dogbeanidcat1classcom。kuang。pojo。Catbeanidcat2classcom。kuang。pojo。Catbeaniduserclasscom。kuang。pojo。User 测试:结果OK 配置文件2:beans。xml,删掉cat2beaniddogclasscom。kuang。pojo。Dogbeanidcat1classcom。kuang。pojo。Cat 实体类上只保留注解ResourceprivateCatcat;ResourceprivateDogdog; 结果:OK 结论:先进行byName查找,失败;再进行byType查找,成功。5。3小结 Autowired与Resource异同: 1、Autowired与Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。 2、Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:Autowired(requiredfalse),如果我们想使用名称装配可以结合Qualifier注解进行使用 3、Resource(属于J2EE规范),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。 它们的作用相同都是用注解方式注入对象,但执行顺序不同。Autowired先byType,Resource先byName。