spring学习笔记3——注入依赖对象

来源:互联网 发布:qq飞车杀人蜂数据 编辑:程序博客网 时间:2024/06/22 23:42

一、   注入依赖对象

       注入依赖对象有手工装配和自动装配两种方式。而所谓的装配就是创建应用对象之间的协作关系的行为(个人感觉就是依赖注入,但依赖注入有三种方法,分别是构造器注入、setter注入,和接口注入,而装配的方法没有接口注入这一概念,其手工装配包含了:构造器注入、setter注入和注解注入。这一点有点模糊,如果有大神对这方面理解得透彻的话,请在评价那里留言)。

 

二、手工装配

1、构造器注入

       这里以“bean应用”歌手唱歌为例,为singer类添加一歌名属性song,并通过构造器注入将song注入。

修改singer类,添加构造函数,其参数为为song

 

application.xml中用<constructor-arg>注入song

 

注:index表示参数的位置,value表示参数值

Test类中,代码如下

 

此时运行Test类,控制台输出

 

注入成功!!!

这只是值属性的注入,但对象的注入也是类型。比如歌手除了唱歌,他还要弹吉他。

这里建一个tool的包,并在里面接一个工具的接口Tool,接口有一方法perform()

 

建一个Guitar类,实现Tool接口

 

修改singer类,在构造器加一Tool属性

 

application.xml中注入Guitar类(先实例化Guitar再注入)

 

注:用ref引用Guitar对象

此时运行Test,控制台输出

 

构造注入完成

 

2setter注入(以上面的例子)

首先删掉singer类构造方法,并未songguitar生成set方法

 

application.xml中用<property>注入song值和Guitar

 

注:属性值用value,对象用ref

运行Test类,控制台输出

 

 3、注解注入

Spring3支持@Atutowierd@Inject@Resource三种,但Spring容器默认禁用注解装配。启用注解的方式很简单,就是使用springcontext命名空间配置中的<context:annotation-config>元素,application的配置如下:

 

注:个人发现在spring-context-3.0.xsd的版本号可以兼容比jar包的版本号小,比如我在项目用了3.1版本,那我在spring-context-3.0.xsd的版本号位置写3.13.0都没问题,但换成了3.2就出错了(但不知道原理)

1) @Atutowierd(默认按类型装配)

   这里同样把Guitar类注入到Singer类中,首先,我们这样在Tool guitar前面加入@Atutowierd

  

注:删掉setGuitar()不影响程序

然后删掉application.xml<bean id=”singer”>中的属性

 

此时运行Test类,就可以正常输出。

@Atutowierd除了可以标注在定义属性的地方,还可以标注在需要装配bean引用的任意地方,比如setter、构造器(我标注构造器时,有两个参数时,会出错,不懂)。但如果只@Atutowierd时,缺点比较大,就是应用中必须只有一个bean合适装配到@Atutowierd标注的属性或参数中,否则就会出错。

解决没有合适的bean注入问题:

@Atutowierd提供了required属性,该属性默认为true,当将属性设置为false时,当找不到适合的bean时,表示注入NULL值。如修改Singer类,添加required属性

 

然后删掉application.xml中的<bean id=”guitar”>

 

此时运行并没有报错

 

解决多个bean注入问题:

这里,我添加了一个Piano类,继承于Tool

 

然后在application.xml中声明guitarpiano

 

同时将Singer类中Tool guitar,修改为Tool tool

 

此时运行就会报错。(之所以将Singer类中Tool guitar,修改为Tool tool,因为我发现该注解,如果有两个适合的beanspring会根据属性名称装配(即装配与属性具有相同名称的bean)。同时属性名为guitar也不符合面向接口编程,呵呵)

接着多个bean注入的问题,就是spring提供了@Qualifier(“bean的名称”),以实现按名字装配如,在@Atutowierd下添加@Qualifier(“piano”),那就会注入bean名字为pianobean

 

此时运行控制台输出

 

 

2@Resource(默认按名称装配,当找不到与名称匹配的bean才会按类型匹配)

   @Resource有一个name属性,用于按名称装配  比如修改Singer类,将@Resource注入到Tool

 

   如果没有写入属性,它会寻找与所标注的属性名相同的bean,再不不到的话,它会按类型装配。

   注:@Resource存在与JDK6中,但不是spring自带的,如@Atutowierd也只可以有一个适合的bean,但找了写材料,有些说法是注解所标注的依赖关系必须存在。个人推荐还是使用@Atutowierd,耦合性比较好。

 

3@Inject

   @Atutowierd也是默认根据类型装配,但该注解没有required属性,所以注解所标注的依赖关系必须存在,不过,对于有多个bean适合装配的时候,@Inject提供了@Named(“bean的名称”)。实际上,@Named就是一个使用@Qualifier注解所标注的注解。(由于找不到需要的包,这里就不做例子了)

 

4)除了对象的注解,还有值的注解@Value()

   如,为Singer类的song注入“Hear Me Cry

  

   此时运行Test类,控制台输出

    

   细看,会发现其实这和直接给song赋值并没有不同。但如果能借助SpEL表达式,那song也是可以动态的赋值了。举例说明一下

   首先为application.xml添加命名空间util

  

  在src下创建Song.properties,里面的值是

   

   application.xml中定义Util

  

   @value()取值

   

   此时运行Test,控制台输出

   

4、集合类型注入

   Spring提供了急着集合类型的注入方法,有setlistmapproperties。这里,如果一个singer想唱几首歌的话,我们可以在Singer类中设置一个songs属性,并为其生成setter方法

   1)Set的用法

     

     接着在application.xml配置着<set>

    

     <propery>中定义set很简单的,其值有<value>即可

     运行Test,控制台输出

    

     2List的用法(和set相识)

       

       接着在application.xml配置着<list>

      

       运行Test,跟Set例子有相同输出

    3map的用法

       Map是基于键值对存值的,这里,我们为标出歌曲对应的语言。先为singer定义songs属性

      

       application.xml中设置map

     

     注:map的值需放在value属性中

    此时运行Test控制台输出

     

  4properties(与map相似,但键值对必须都是string

        

        application.xml配置

        

        此时运行Test,跟set例子有相同输出

 

三、自动装配

     Spring提供了四种自动装配策略,byNamebyTypeconstructorautodetect

1)byName:把与bean的属性具有相同名字(或者ID)的其他bean自动装配到Bean对应的属性中,如果没有个属性名字相匹配的bean,则该属性不进行装配,如果发现多个,则抛出异常。

比如将guitar注入到singer

修改Singer类的代码

 

注:必须有setter方法,否则不成功

修改application.xml的代码

 

这里很简单,只有添加autowire属性。

运行Test,此时控制台输出

 

2)byType:把与bean的属性具有相同类型的其他bean自动装配到bean的对象属性中,找不到相应类型,则不装配。

3)constructor:把与bean的构造器入参具有相同类型的其他bean自动装配到bean构造器的对应入参中

4)autodetect:先尝试constructor自动装配,如果失败,在尝试使用byType进行自动装配

3个例子类似。一个个bean写自动装配策略可能有时过于繁琐,我们也可以全局设置,就是在beans中添加“default-autowier”。

 

默认情况下,该属性值是no

 

四、自动扫描和管理Bean

Spring引人了组件自动扫描急着,他可以在类路径底下寻找标注了@Component@service@Controller@Repository注解的类,并把这些类纳入spring容器中管理。它的作用和XML文件中使用bean节点配置组件是一样的。

要配置spring自动检测,需要开启<context:component-scan>,它包含了<context:annotation-config>的内容。

 

默认情况下<context:component-scan>会查找使用了@Component@Service@Controller@Repository注解的类。其中,@Service用于标注业务层组件,@Controller用于标注控制层组件,@Repository用于标注数据库访问组件,@Component标注不好归类的组件(也就是说什么类都可以标注)。其实,目前四个注解是没有区别的。

做个例子,实现自动扫描和管理Bean功能。

application.xml中启动自动扫描功能,并在service包下扫描。

 

singer类里添加@Component

 

运行Test类,此时控制台属性

 

这里也可以看到,基于@Value注解依旧成功,却注入后,bean的名称为给类的名称(首字母为小写)。如果要指定该类的名称,可以在@Component后面加括号,括号里面是类名称@Component(“名称”)

此时,我们创建的bean其实是单例的,但通过@scope设置

当然,spring提供了其他注解为我们服务,比如用@PostConstruct代替init-method="",用@PreDestroy代替destroy-method=""

 

 

PS在个人测试中,如让spring自动扫描项目所有包

 

然后用注解将Tool注入到Singer类中,如果把注入标注在属性字段上

 

此时行项目会报错,它没法根据名字去注入@Qualifier失效。但是如果将注解标注在setter方法上,项目又神奇的跑起来了(啥道理啊,哪个大神懂)。

0 0