Sping IOC依赖注入的5种方式

前端之家收集整理的这篇文章主要介绍了Sping IOC依赖注入的5种方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。

spring有多种依赖注入的形式,下面仅介绍spring通过xml进行IOC配置的方式:
  • Set注入
这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口):
Java代码
  1. packagecom.bless.springdemo.action;
  2. publicclassSpringAction{
  3. //注入对象springDao
  4. privateSpringDaospringDao;
  5. //一定要写被注入对象的set方法
  6. voidsetSpringDao(SpringDaospringDao){
  7. this.springDao=springDao;
  8. }
  9. voidok(){
  10. springDao.ok();
  11. }
随后编写spring的xml文件,<bean>中的name属性是class属性的一个别名,class属性指类的全名,因为在SpringAction中有一个公共属性Springdao,所以要在<bean>标签中创建一个<property>标签指定SpringDao。<property>标签中的name就是SpringAction类中的SpringDao属性名,ref指下面<bean name="springDao"...>,这样其实是spring将SpringDaoImpl对象实例化并且调用SpringAction的 setSpringDao方法将SpringDao注入
Java代码
  1. <!--配置bean,配置后该类由spring管理-->
  2. <beanname="springAction"class="com.bless.springdemo.action.SpringAction">
  3. <!--(1)依赖注入,配置当前类中相应的属性-->
  4. <propertyname="springDao"ref="springDao"></property>
  5. </bean>
  6. <beanname="springDao"class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
  • 构造器注入
这种方式的注入是指带有参数的构造函数注入,看下面的例子,我创建了两个成员变量SpringDao和User,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来:
Java代码
  1. classSpringAction{
  2. //注入对象springDao
  3. privateSpringDaospringDao;
  4. privateUseruser;
  5. publicSpringAction(SpringDaospringDao,Useruser){
  6. this.springDao=springDao;
  7. this.user=user;
  8. System.out.println("构造方法调用springDao和user");
  9. }
  10. voidsave(){
  11. user.setName("卡卡");
  12. springDao.save(user);
  13. }
在XML文件中同样不用<property>的形式,而是使用<constructor-arg>标签,ref属性同样指向其它<bean>标签的name属性
Xml代码
    <!--配置bean,配置后该类由spring管理-->
  1. <beanname="springAction"class="com.bless.springdemo.action.SpringAction">
  2. <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
  3. constructor-argref="springDao"></constructor-argconstructor-argref="user"beanbeanname="springDao"class="com.bless.springdemo.dao.impl.SpringDaoImpl"beanname="user"class="com.bless.springdemo.vo.User">
解决构造方法参数的不确定性,你可能会遇到构造方法传入的两参数都是同类型的,为了分清哪个该赋对应值,则需要进行一些小处理:
下面是设置index,就是参数位置:
constructor-argindex="0"ref="springDao"constructor-argindex="1"ref="user">
另一种是设置参数类型:
constructor-argtype="java.lang.String"ref=""/>
静态工厂顾名思义,就是通过调用静态工厂的方法获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过spring注入的形式获取
packagecom.bless.springdemo.factory;
  • importcom.bless.springdemo.dao.FactoryDao;
  • importcom.bless.springdemo.dao.impl.FactoryDaoImpl;
  • importcom.bless.springdemo.dao.impl.StaticFacotryDaoImpl;
  • classDaoFactory{
  • //静态工厂
  • staticfinalFactoryDaogetStaticFactoryDaoImpl(){
  • returnnewStaticFacotryDaoImpl();
  • }

  • 同样看关键类,这里我需要注入一个FactoryDao对象,这里看起来跟第一种注入一模一样,但是看随后的xml会发现有很大差别:
    //注入对象
  • privateFactoryDaostaticFactoryDao;
  • voidstaticFactoryOk(){
  • staticFactoryDao.saveFactory();
  • //注入对象的set方法
  • voidsetStaticFactoryDao(FactoryDaostaticFactoryDao){
  • this.staticFactoryDao=staticFactoryDao;
  • Spring的IOC配置文件,注意看<bean name="staticFactoryDao">指向的class并不是FactoryDao的实现类,而是指向静态工厂 DaoFactory,并且配置 factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法
  • Xml代码
      >
    1. <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->
    2. propertyname="staticFactoryDao"ref="staticFactoryDao"property<!--(3)此处获取对象的方式是从工厂类中获取静态方法-->
    3. beanname="staticFactoryDao"class="com.bless.springdemo.factory.DaoFactory"factory-method="getStaticFactoryDaoImpl"
    实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法
    //实例工厂
  • publicFactoryDaogetFactoryDaoImpl(){
  • newFactoryDaoImpl();
  • }

  • 那么下面这个类没什么说的,跟前面也很相似,但是我们需要通过实例工厂类创建FactoryDao对象:
    privateFactoryDaofactoryDao;
  • voidfactoryOk(){
  • factoryDao.saveFactory();
  • voidsetFactoryDao(FactoryDaofactoryDao){
  • this.factoryDao=factoryDao;
  • 最后看spring配置文件
  • <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->
  • propertyname="factoryDao"ref="factoryDao"<!--(4)此处获取对象的方式是从工厂类中获取实例方法-->
  • beanname="daoFactory"class="com.bless.springdemo.factory.DaoFactory"beanname="factoryDao"factory-bean="daoFactory"factory-method="getFactoryDaoImpl">
  • 使用字段(Filed)注入(用注解方式)

    在Spring中,注入依赖对象可以采用手工装配或自动装配,在实际应用开发中建议使用手工装配,因为自动装配会产生许多未知情况,开发人员无法预见最终的装配结果。

    手工装配依赖对象又分为两种方式:

    一种是在XML文件中,通过在bean节点下配置;如上面讲到的使用属性的setter方法注入依赖对象和使用构造器方法注入依赖对象都是这种方式。

    另一种就是在java代码中使用注解的方式进行装配,在代码中加入@Resource或者@Autowired

    怎样使用注解的方式来为某个bena注入依赖对象呢?

    首先,我们需要在Spring容器的配置文件applicationContext.Xml文件中配置以下信息,该信心是一个Spring配置文件的模板:

    <?xmlversion="1.0"encoding="UTF-8"?>

    <beans

    xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:p="http://www.springframework.org/schema/p"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-2.5.xsd

    ">

    </beans>

    注意:只有配置了红色部分的代码才可以引入注解的命名空间,否则报错。以上的配置隐式的注册了多个对注释进行解析的处理器:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。

    其次,在配置文件中打开<context:annotation-config>节点,告诉Spring容器可以用注解的方式注入依赖对象;其在配置文件中的代码如下:

    <beans>

    ……

    <context:annotation-config></context:annotation-config>

    第三,在配置文件中配置bean对象,如下:

    <beanid="userDao"class="com.springtest.dao.impl.UserDAOImpl"></bean>

    <beanid="userBiz"class="com.springtest.biz.impl.UserBizImpl"></bean>

    第四,在需要依赖注入的BIZ类中,声明一个依赖对象,不用生成该依赖对象的setter方法,并且为该对象添加注解:

    publicclassUserBizImplimplementsUserBiz{

    @Resource(name="userDao")

    privateUserDAOuserDao=null;

    publicvoidaddUser(){

    this.userDao.addUser();

    }

    }

    其中,在Java代码中可以使用@Autowired或@Resource注解方式进行Spring的依赖注入。两者的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配。

    比如:我们用@Autowired为上面的代码UserDAO接口的实例对象进行注解,它会到Spring容器中去寻找与UserDAO对象相匹配的类型,如果找到该类型则将该类型注入到userdao字段中;

    如果用@Resource进行依赖注入,它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型,例如:@Resource(name="userDao"),如果没有找到该名称,则会按照类型去寻找,找到之后,会对字段userDao进行注入。

    通常我们使用@Resource。

    使用注解注入依赖对象不用再在代码中写依赖对象的setter方法或者该类的构造方法,并且不用再配置文件中配置大量的依赖对象,使代码更加简洁,清晰,易于维护。

    在SpringIOC编程的实际开发中推荐使用注解的方式进行依赖注入。

    依赖注入—自动装配

    Spring中提供了自动装配依赖对象的机制,但是在实际应用中并不推荐使用自动装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。

    自动装配是在配置文件中实现的,如下:

    <beanid="***"class="***"autowire="byType">

    只需要配置一个autowire属性即可完成自动装配,不用再配置文件中写<property>,但是在类中还是要生成依赖对象的setter方法

    Autowire的属性值有如下几个:

    ·byType按类型装配可以根据属性类型,在容器中寻找该类型匹配的bean,如有多个,则会抛出异常,如果没有找到,则属性值为null;

    ·byName名称装配可以根据属性名称在容器中查询与该属性名称相同的bean,如果没有找到,则属性值为null;

    ·constructor与byType方式相似,不同之处在与它应用于构造器参数,如果在容器中没有找到与构造器参数类型一致的bean,那么将抛出异常;

    ·autodetect通过bean类的自省机制(introspection)来决定是使用constructor还是byType的方式进行自动装配。如果发现默认的构造器,那么将使用byType的方式

    猜你在找的设计模式相关文章