依赖注入的配置

Spring的依赖注入分为基于构造函数的依赖注入基于setter方法的依赖注入

基于构造函数的依赖注入

        <!-- 通过构造器参数索引方式依赖注入 -->
<bean id="byIndex" class="cn.javass.spring.chapter3.HelloImpl3">
<constructor-arg index="0" value="Hello World!"/>
<constructor-arg index="1" value="1"/>
</bean>
<!-- 通过构造器参数类型方式依赖注入 -->
<bean id="byType" class="cn.javass.spring.chapter3.HelloImpl3">
<constructor-arg type="java.lang.String" value="Hello World!"/>
<constructor-arg type="int" value="2"/>
</bean>
<!-- 通过构造器参数名称方式依赖注入 -->
<bean id="byName" class="cn.javass.spring.chapter3.HelloImpl3">
<constructor-arg name="message" value="Hello World!"/>
<constructor-arg name="index" value="3"/>
</bean>
<!-- 通过静态的工厂方法注入 -->
<bean id="byName" class="cn.javass.spring.chapter3.HelloImpl3" factory-method="getBean">
<constructor-arg name="message" value="Hello World!"/>
<constructor-arg name="index" value="3"/>
</bean>

基于setter方法的依赖注入

    <bean class="...HelloImpl4">
<property name="message" value="Hello"/>
<property name="index" value="1"/> //value中的值全部是字符串形式,如果转换出错会报异常
</bean>
<bean id="Hello2" class="com.csx.personal.web.services.HelloImpl2">
<property name="msg" ref="message"/> //msg属性是一个类对象
</bean>

循环依赖:创建Bean A需要Bean B,创建Bean B需要Bean C,创建Bean C需要Bean A 这样就形成了循环依赖。 Spring的解决方案:Spring创建Bean的时候会维护一个池,在创建A的时候会去池中查找A是否在池子中,假如发现就抛出循环依赖异常。

避免依赖注入时的循环依赖:可以使用setter方式注入,不要使用构造器形式的注入。

依赖配置常见列子

常量值注入配置

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="masterkaoli"/>
</bean>

注入其他Bean

这边分别给出了一个引用当前容器和引用父容器中Bean的列子。

   <bean id="Hello2" class="com.csx.personal.web.services.HelloImpl2">
<property name="msg"> //msg属性是一个类对象
<ref bean="message"/> //引用同一个容器中id="message"的Bean
</property>
</bean> <!-- 引用父容器中的Bean -->
<!-- in the parent context -->
<bean id="accountService" class="com.something.SimpleAccountService">
<!-- insert dependencies as required as here -->
</bean> <!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
</property>
<!-- insert other configuration and dependencies as required here -->
</bean>

注入内部Bean

内部bean:这种bean一般只让某个外部bean使用(和内部类相似),不让容器中的其他Bean使用。

    <bean id="outer" class="...">
<property name="target">
<!-- this is the inner bean -->
<bean class="com.example.Person">
<property name="name" value="Fiona Apple"/>
<property name="age" value="25"/>
</bean>
</property>
</bean>

集合的注入

集合类的注入建议使用util命名空间

    <util:map id="myMap" key-type="java.lang.String" value-type="java.lang.String">
<entry key="key1" value="chen"/>
<entry key="key2" value="zhao"/>
</util:map> <util:list id="myList" value-type="java.lang.String">
<value>chen</value>
<value>zhao</value>
</util:list> <util:set id="mySet" value-type="java.lang.String" scope="singleton">
<value>chen</value>
<value>zhao</value>
</util:set> <util:properties id="myProp" location="classpath:xx.properties"/>

null值和空字符串的注入

   <bean class="...HelloImpl4">
<property name="message"><null/></property> //null值
<property name="index" value=""/> //空字符串
</bean>

使用depends-on属性

depends-on属性用来指定bean的初始化顺序。这个属性只对scope是单列的bean生效

    <!--在实例化beanOne之前先实例化manager和accountDao这两个bean-->
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

懒加载

bean的定义中有一个lazy-init这个属性,用来设置单列bean在容器初始化后是否实例化这个bean。默认情况下容器是会实例化所有单例bean的,我们也建议这么做,因为这样能在容器初始化阶段就发现bean配置是否正确。如果一个Bean按照下面的设置,lazy-init被设置为true那么它不会被容器预初始化,只有在被使用的时候才被初始化。但是如果有一个单列类依赖了这个Bean,那么这个被设置成懒加载的Bean还是会被预初始化。

   <bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>

如果想设置全局的单例Bean都不要预先初始化,那么可以在xml中做如下设置:

    <beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>

Autowiring相关

当我们要往一个bean的某个属性里注入另外一个bean,我们会使用property +ref标签的形式。但是对于大型项目,假设有一个bean A被多个bean引用注入,如果A的id因为某种原因修改了,那么所有引用了A的bean的ref标签内容都得修改,这时候如果使用autowire="byType",那么引用了A的bean就完全不用修改了。

 <!--autowire的用法如下,对某个Bean配置autowire模式 -->
<!--和给Bean的属性添加@AutoWired注解的效果一致-->
<bean id="auto" class="example.autoBean" autowire="byType"/>

autowire的几种模式:

  • no模式:也是默认模式,这种模式下不会进行自动属性注入,需要我们自己通过value或者ref属性进行配置;
  • byName模式:通过属性的名称自动装配,Spring会在容器中查找名称与bean属性名称一致的bean,并自动注入到bean属性中。当然bean的属性需要有setter方法。例如:bean A有个属性master,master的setter方法就是setMaster,A设置了autowire="byName",那么Spring就会在容器中查找名为master的bean通过setMaster方法注入到A中;
  • byType:通过类型自动装配(注入)。Spring会在容器中查找类(Class)与bean属性类一致的bean,并自动注入到bean属性中,如果容器中包含多个这个类型的bean,Spring将抛出异常。如果没有找到这个类型的bean,那么注入动作将不会执行;
  • constructor:类似于byType,但是是通过构造函数的参数类型来匹配。假设bean A有构造函数A(B b, C c),那么Spring会在容器中查找类型为B和C的bean通过构造函数A(B b, C c)注入到A中。与byType一样,如果存在多个bean类型为B或者C,则会抛出异常。但时与byType不同的是,如果在容器中找不到匹配的类的bean,将抛出异常,因为Spring无法调用构造函数实例化这个bean;
  • default : 采用父级标签(即beans标签的default-autowire属性)的配置。

需要注意的是上面这5中方式注入都需要我们提供相应的setter方法,通过@Autowired的方式不需要提供相应的setter方法。

自动装配的缺点

  • 属性和构造函数参数设置中的显式依赖项会覆盖自动装配;

将Bean排除自动装配

如果按照下面的方式配置了Bean,那么这个Bean将不会作为自动装配的候选Bean。但是autowire-candidate自会对byType形式的自动注入生效,如果我们是通过byName的形式进行自动注入,那么还是能注入这个Bean。

    <bean id="auto" class="example.autoBean" autowire="byType" autowire-candidate="false"/>

如果我们只想让某些Bean作为自动装配的候选Bean,那么可以进行全局设置。如果做了下面的配置,那么只有id为bean1和bean2的Bean才会成为自动装配的候选Bean。同时default-autowire-candidates的值支持正则表达式形式。但是强烈建议不要配置这个选项的值,使用默认的配置就行。

    <beans default-autowire-candidates="bean1,bean2">
</beans>

方法注入(单例依赖原型Bean)

我们在配置bean的时候首先要考虑这个bean是要配置成单例模式还是其他模式。 在我们的应用中,绝大多数类都是单例类。当单例类引用单例类,或者原型类引用原型类、单例类时,我们只要像普通的配置方式就行了。但是当一个单例类引用原型类时,就会出现问题。这种情况可以使用下面的方式进行注入。

   @Service
@Scope("prototype")
public class MyService1 {
public void service() {
System.out.println(this.toString() + ":id");
}
} @Service
public abstract class MyService { private MyService1 service1;
public void useService(){
service1 = createService1();
service1.service();
} @Lookup("myService1")
public abstract MyService1 createService1(); } //也可以这样配置bean
<bean id="serviceC" class="com.csx.demo.springdemo.service.ServiceC">
<lookup-method bean="serviceD" name="createService"/>
</bean>
<bean id="serviceD" class="com.csx.demo.springdemo.service.ServiceD" scope="prototype"/>

Spring系列.依赖注入配置的更多相关文章

  1. SpringBoot系列: 理解 Spring 的依赖注入(一)

    ==============================Spring 的依赖注入==============================对于 Spring 程序, Spring 框架为我们提供 ...

  2. Spring.NET依赖注入框架学习--简介

    Spring.NET依赖注入框架学习--Spring.NET简介 概述 Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序.它提供了很多方面的功能,比如依赖注入. ...

  3. Bean 注解(Annotation)配置(3)- 依赖注入配置

    Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...

  4. Bean XML 配置(3)- 依赖注入配置

    Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...

  5. (spring-第3回【IoC基础篇】)spring的依赖注入-属性、构造函数、工厂方法等的注入(基于XML)

    Spring要把xml配置中bean的属性实例化为具体的bean,"依赖注入"是关卡.所谓的"依赖注入",就是把应用程序对bean的属性依赖都注入到spring ...

  6. Spring的依赖注入(DI)三种方式

    Spring依赖注入(DI)的三种方式,分别为: 1.  接口注入 2.  Setter方法注入 3.  构造方法注入 下面介绍一下这三种依赖注入在Spring中是怎么样实现的. 首先我们需要以下几个 ...

  7. 一步一步深入spring(3)--spring的依赖注入方式

    对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程,sprin ...

  8. spring的依赖注入是什么意思

    最近学习spring框架,对依赖注入有些模糊,遂上网翻阅资料,做了下列总结,原博客为CSDN 南夏的 spring的依赖注入是什么意思,侵删! Spring 能有效地组织J2EE应用各层的对象.不管是 ...

  9. Spring.NET依赖注入框架学习--简单对象注入

    Spring.NET依赖注入框架学习--简单对象注入 在前面的俩篇中讲解了依赖注入的概念以及Spring.NET框架的核心模块介绍,今天就要看看怎么来使用Spring.NET实现一个简单的对象注入 常 ...

随机推荐

  1. mysql小白系列_13 Online DDL

    Online DDL: 一.FIC之前的添加删除二级索引: 1.首先创建临时表,定义目标新表的选项和索引 2.逐行拷贝数据到临时表 3.插入行时更新索引信息 4.数据全部被拷贝到新表后,删除旧表,re ...

  2. Struts2导图

  3. Word与Excel中,如何输入✔标志

    为了表达值的对错,或者相关任务是否完成,我们需要在word及excel中输入[√]和[x] Word与Excel中如何在方框“口”中打勾[√]和[x],在Word中打钩的方法有3种:第一种,在插入特殊 ...

  4. Java入门以及使用IDEA安装和使用

    目录 JAVA第一个程序 HelloWorld 可能会遇到的情况 JAVA程序运行机制 IDEA安装 什么是IDE IDEA介绍 IDEA下载 IDEA基本使用 关于一些创建项目的小tips JAVA ...

  5. IDEA提高开发效率的7个插件

    IDEA提高开发效率的7个插件 1. 多行编辑 先来体验一下从xml文件拷贝字段新建实体对象 一般我们为了新建多表连接后映射的 ResultMap ,耗费不少时间,那么我们就来试一试这个多行编辑 表字 ...

  6. 【python爬虫】解决歌荒,下歌利器

    python下载图片,mp3,想必很多人都早已耳闻,今天给大家来点不一样的, 让你下载高逼格高品质,带进度条,实时显示下载速度 详见源码:https://www.kesci.com/home/proj ...

  7. PHP SESSION 操作

    Session的声明与使用 Session的设置不同于Cookie,必须先启动,在PHP中必须调用session_start().session_start()函数的语法格式如下: Bool sess ...

  8. 查看包名和Activity的小工具

    添加到右键菜单,很方便. 做个记录:请移步原文

  9. web自动化之Select标签操作

    from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from seleni ...

  10. JavaScript 实现 冒泡排序

        <script>         //数组排序(冒泡排序)         //冒泡排序是一种算法,把一系列的数据按照一定的循序进行排列显示(从小到大或从大到小)          ...