9.Spring的几种注入方式

本文详细介绍了Spring框架的四种依赖注入方式:属性注入、构造器注入、静态工厂注入和注解注入。通过示例代码展示了每种注入方式的具体使用,包括XML配置和注解配置,帮助读者深入理解Spring的IoC容器工作原理。

几种注入方式:

1、属性注入(使用属性的setter方法注入)

2、构造方法注入

3、工厂方法注入(静态工厂、实例工厂(非静态工厂))

4注解注入

 

1.Set注入

这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个privateSpringDao成员变量,然后创建SpringDaoset方法(这是ioc的注入入口):

package com.bless.springdemo.action;

public class SpringAction {

//注入对象springDao

private SpringDao springDao;

//一定要写被注入对象的set方法

public void setSpringDao(SpringDaospringDao) {

this.springDao = springDao;

}

 

public void ok(){

springDao.ok();

}

}

XML配置:

<!--配置bean,配置后该类由spring管理-->

<bean name="springAction" class="com.bless.springdemo.action.SpringAction">

<!--(1)依赖注入,配置当前类中相应的属性-->

<propertyname="springDao" ref="springDao"></property>

</bean>

<beanname="springDao"class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

2.构造器注入

这种方式的注入是指带有参数的构造函数注入,看下面的例子,我创建了两个成员变量SpringDaoUser,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来:

1.  publicclass SpringAction {

2.      //注入对象springDao

3.      private SpringDao springDao;

4.      private User user;

5.   

6.      publicSpringAction(SpringDao springDao,Useruser){

7.      this.springDao = springDao;

8.      this.user = user;

9.      System.out.println("构造方法调用springDaouser");

10.}

11. 

12.publicvoidsave(){

13.    user.setName("卡卡");

14.    springDao.save(user);

15.}

16.}

在XML文件中同样不用的形式,而是使用标签,ref属性同样指向其它标签的name属性:

<!--配置bean,配置后该类由spring管理-->

<beanname="springAction"class="com.bless.springdemo.action.SpringAction">

<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->

<constructor-argref="springDao"></constructor-arg>

<constructor-argref="user"></constructor-arg>

</bean>

<beanname="springDao"class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

<beanname="user"class="com.bless.springdemo.vo.User"></bean>

·         

解决构造方法参数的不确定性,你可能会遇到构造方法传入的两参数都是同类型的,为了分清哪个该赋对应值,则需要进行一些小处理:

下面是设置index,就是参数位置:

<beanname="springAction"class="com.bless.springdemo.action.SpringAction">

<constructor-argindex="0"ref="springDao"></constructor-arg>

<constructor-argindex="1"ref="user"></constructor-arg>

</bean>

另一种是设置参数类型:

<constructor-argtype="java.lang.String" ref=""/>

3工厂方法

3.1静态工厂的方法注入

静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过”工程类.静态方法()”来获取对象,而是依然通过spring注入的形式获取:

package com.bless.springdemo.factory;

 

import com.bless.springdemo.dao.FactoryDao;

import com.bless.springdemo.dao.impl.FactoryDaoImpl;

import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl;

 

public class DaoFactory {

//静态工厂

public static final FactoryDao getStaticFactoryDaoImpl(){

    return newStaticFacotryDaoImpl();

    }

}

同样看关键类,这里我需要注入一个FactoryDao对象,这里看起来跟第一种注入一模一样,但是看随后的xml会发现有很大差别:

publicclass SpringAction {

//注入对象

private FactoryDaostaticFactoryDao;

 

publicvoidstaticFactoryOk(){

    staticFactoryDao.saveFactory();

}

//注入对象的set方法

publicvoidsetStaticFactoryDao(FactoryDao staticFactoryDao) {

    this.staticFactoryDao =staticFactoryDao;

}

}

Spring的IOC配置文件,注意看指向的class并不是FactoryDao的实现类,而是指向静态工厂DaoFactory,并且配置factory-method=”getStaticFactoryDaoImpl”指定调用哪个工厂方法:

<!--配置bean,配置后该类由spring管理-->

<beanname="springAction"class="com.bless.springdemo.action.SpringAction" >

<!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->

<propertyname="staticFactoryDao"ref="staticFactoryDao"></property>

</property>

</bean>

<!--(3)此处获取对象的方式是从工厂类中获取静态方法-->

<beanname="staticFactoryDao"class="com.bless.springdemo.factory.DaoFactory"factory-method="getStaticFactoryDaoImpl"></bean>

3.2实例工厂的方法注入

实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法:

public class DaoFactory { 
//实例工厂 
public FactoryDao getFactoryDaoImpl(){ 
    return new FactoryDaoImpl(); 
} 
}

那么下面这个类没什么说的,跟前面也很相似,但是我们需要通过实例工厂类创建FactoryDao对象:

public class SpringAction { 
//注入对象 
private FactoryDao factoryDao; 
 
public void factoryOk(){ 
    factoryDao.saveFactory(); 
} 
 
public void setFactoryDao(FactoryDao factoryDao) { 
    this.factoryDao = factoryDao; 
    } 
} 

最后看spring配置文件:

<!--配置bean,配置后该类由spring管理--> 
<bean name="springAction" class="com.bless.springdemo.action.SpringAction"> 
<!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)--> 
<property name="factoryDao" ref="factoryDao"></property> 
</bean> 
<!--(4)此处获取对象的方式是从工厂类中获取实例方法--> 
<bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean> 
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean> 

 

 

Spring依赖注入:注解注入总结

注解注入顾名思义就是通过注解来实现注入,Spring和注入相关的常见注解有AutowiredResourceQualifierServiceControllerRepositoryComponent

       基本上项目都有用过了,接下来将一个一个详细来学习一下吧。

·        Autowired是自动注入,自动从spring的上下文找到合适的bean来注入

·        Resource用来指定名称注入

·        QualifierAutowired配合使用,指定bean的名称

·        ServiceControllerRepository分别标记类是Service层类,Controller层类,数据存储层的类,spring扫描注解配置时,会标记这些类要生成bean(生成bean,然后需要的时候就从容器中拿出bean注入到所需要的地方)

·        Component是一种泛指,标记类是组件,spring扫描注解配置时,会标记这些类要生成bean

上面的AutowiredResource是用来修饰字段,构造函数,或者设置方法,并做注入的。而ServiceControllerRepositoryComponent则是用来修饰类,标记这些类要生成bean

下面我们通过实例项目来看下spring注解注入的使用。

首先新建一个maven项目,并在pom中添加spring相关的依赖,如果不知道添加那些依赖,请参照上一篇文章。

然后新建CarDao类,给它添加@Repository注解,如下代码:

package cn.outofmemory.helloannotation;

 

import org.springframework.stereotype.Repository;

 

@Repository

publicclassCarDao {

 

    publicvoid insertCar(String car) {

        String insertMsg = String.format("insertingcar %s", car);

        System.out.println(insertMsg);

    }

 

}

新建CarService类,并给该类标注@Service注解,在这个类中定义CarDao的字段,并通过Autowired来修饰此字段,这样上面定义的CarDao类的实例就会自动注入到CarService的实例中了。

package cn.outofmemory.helloannotation;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

@Service

publicclassCarService {

 

    @Autowired

    privateCarDao carDao;

 

    publicvoid addCar(String car) {

        this.carDao.insertCar(car);

    }

}

注意:Autowired注解有一个可以为空的属性required,可以用来指定字段是否是必须的,如果是必需的,则在找不到合适的实例注入时会抛出异常。

下面我们在App.java中使用上面测试下注解注入:

package cn.outofmemory.helloannotation;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

 

/**

 * Hello world!

 *

 */

publicclassApp

{

    publicstaticvoid main( String[] args )

    {

        ApplicationContext appContext = newAnnotationConfigApplicationContext("cn.outofmemory.helloannotation");

        CarService service =appContext.getBean(CarService.class);

       service.addCar("宝马");

    }

}

在上面的main方法中首先我们初始化了appContext,他是AnnotationConfigApplicationContext,它的构造函数接受一个package的名称,来限定要扫描的package。然后就可以通过appContextgetBean方法获得CarService的实例了。

上面的例子非常简单,单纯的使用AnnotationConfigApplicationContext就可以了,但是在实际项目中情况往往没有这么简单,还是需要spring配置文件的。在spring配置文件中也可以通过下面的配置让spring自动扫描注解配置。

    <!-- beanannotation driven -->

    <context:annotation-config/>

    <context:component-scanbase-package="cn.outofmemory.helloannotation">

    </context:component-scan>

下面我们看下混合使用spring配置和注解的例子,首先在项目中添加source foldersrc/main/resources,并添加spring.xml, 其内容如下:

<?xml version="1.0" encoding="utf-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

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

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

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

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

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

 http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 

    <!-- beanannotation driven -->

    <context:annotation-config/>

    <context:component-scanbase-package="cn.outofmemory.helloannotation">

    </context:component-scan>

 

    <beanid="sqliteCarDao"class="cn.outofmemory.helloannotation.CarDao">

        <constructor-argname="driver"value="sqlite"/>

    </bean>

 </beans>

在上面的配置文件中,我们通过context:annotation-configcontext:component-sacn节点来指定要扫描注解注入,然后又定义了一个idsqliteCarDaobean,它的构造函数的driver值为sqlite

我们修改下App.java使用xml配置文件,再运行下App看下会怎样。

package cn.outofmemory.helloannotation;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

/**

 * Hello world!

 *

 */

publicclassApp

{

    publicstaticvoid main( String[] args )

    {

        //ApplicationContextappContext = newAnnotationConfigApplicationContext("cn.outofmemory.helloannotation");

 

        ApplicationContext appContext = newClassPathXmlApplicationContext("/spring.xml");

        CarService service =appContext.getBean(CarService.class);

       service.addCar("宝马");

    }

}

运行程序发现输出为:inserting car 宝马 into mysql,显然CarService自动注入的CarDao使用了默认构造函数构造的实例。是否可以通过注解指定使用spring.xml中配置的sqliteCarDao呢?

我们可以修改下CarService类,通过Qualifier注解来指定要使用的bean的名字。

如下,在指定Autowired注解时,同时指定Qualifier注解指定bean的名字

    @Autowired

    @Qualifier("sqliteCarDao")

    privateCarDao carDao;

重新运行下App.java 这次输出的是inserting car 宝马 into sqlite,这次使用了spring.xml中配置的bean了。

在文中开头我们还提到了Resouce注解,这个注解可以指定名字注入,我们再次修改下CarService类:

    @Resource(name="sqliteCarDao")

    privateCarDao carDao;

javax.annotation.Resource注解实现的效果和@Autowired+@Qualifier的效果是一样的。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值