1.set方法注入
2.构造器注入
3.静态工厂注入
4.实例工厂注入

我使用下面两个类来进行注入的演示,这两个类分别是User和Car类:
Car类:

public class Car {// 只包含基本数据类型的属性private int speed;private double price;public Car() {}public Car(int speed, double price) {this.speed = speed;this.price = price;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Car{" +"speed=" + speed +", price=" + price +'}';}
}

User类:

public class User {private String name;private int age;// 除了上面两个基本数据类型的属性,User还依赖Carprivate Car car;public User() {}public User(String name, int age, Car car) {this.name = name;this.age = age;this.car = car;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +", car=" + car +'}';}
}

1.set注入

有了上面两个类,就可以演示set注入了。需要注意一点,如果需要使用set注入,那么必须要为属性提供set方法,Spring容器就是通过调用bean的set方法为属性注入值的。而在xml文件中,使用set注入的方式就是通过property标签,如下所示:

<!-- 定义car这个bean,id为myCar -->
<bean id="myCar" class="cn.tewuyiang.pojo.Car"><!-- 为car的属性注入值,因为speed和price都是基本数据类型,所以使用value为属性设置值;注意,这里的name为speed和price,不是因为属性名就是speed和price,而是set方法分别为setSpeed和setPrice,名称是通过将set删除,然后将第一个字母变小写得出;--><property name="speed" value="100"/><property name="price" value="99999.9"/>
</bean><!-- 定义user这个bean -->
<bean id="user" class="cn.tewuyiang.pojo.User"><property name="name" value="aaa" /><property name="age" value="123" /><!-- car是引用类型,所以这里使用ref为其注入值,注入的就是上面定义的myCar 基本数据类型或Java包装类型使用value,而引用类型使用ref,引用另外一个bean的id --><property name="car" ref="myCar" />
</bean>

通过上面的配置,就可以为Car和User这两个类型的bean注入值了。需要注意的是,property的name属性,填写的不是属性的名称,而是set方法去除set,然后将第一个字符小写后的结果。对于基本数据类型,或者是Java的包装类型(比如String),使用value注入值,而对于引用类型,则使用ref,传入其他bean的id。接下来就可以测试效果了:

@Test
public void test1() {ApplicationContext context =new ClassPathXmlApplicationContext("classpath:applicationContext.xml");// 获取user这个beanUser user = context.getBean(User.class);// 输出产看结果System.out.println(user);
}

由于user包含car的引用,所以直接输出user,也能够看到car的情况,输入结果如下:

User{name='aaa', age=123, car=Car{speed=100, price=99999.9}}

2.构造器注入

下面来说第二种方式——构造器注入。听名字就可以知道,这种注入值的方式,就是通过调用bean所属类的带参构造器为bean的属性注入值。这也就意味着,如果需要使用构造器注入,就得为类提供包含参数的构造方法。构造器注入,实际上有多种匹配属性值的方式,下面就来一一列举。这里依然使用定义的Car和User这两个类,测试方法以及类的定义都不需要变,需要改变的仅仅是xml配置文件。

(一)匹配构造器的参数名称

需要通过constructor-arg标签为构造器传入参数值,但是每个constructor-arg标签对应哪一个参数值呢?这就有多种方式指定了。第一种就是直接匹配参数名,配置如下:

<bean id="myCar" class="cn.tewuyiang.pojo.Car"><!-- 通过constructor-arg的name属性,指定构造器参数的名称,为参数赋值 --><constructor-arg name="speed" value="100" /><constructor-arg name="price" value="99999.9"/>
</bean><bean id="user" class="cn.tewuyiang.pojo.User"><constructor-arg name="name" value="aaa" /><constructor-arg name="age" value="123" /><!-- 和之前一样,基本数据类型或Java包装类型使用value,而引用类型使用ref,引用另外一个bean的id --><constructor-arg name="car" ref="myCar" />
</bean>

这样就完成了,测试代码和之前一样,运行结果也一样,这里的配置和set注入时的配置几乎一样,除了一个使用property,一个使用constructor-arg。写法上一样,但是表示的含义却完全不同。property的name属性,是通过set方法的名称得来;而constructor-arg的name,则是构造器参数的名称。

(二)匹配构造器的参数下标

上面是通过构造器参数的名称,匹配需要传入的值,那种方式最为直观,而Spring还提供另外两种方式匹配参数,这里就来说说通过参数在参数列表中的下标进行匹配的方式。下面的配置,请结合User和Car的构造方法一起阅读,配置方式如下:

<bean id="car" class="cn.tewuyiang.pojo.Car"><!-- 下标编号从0开始,构造器的第一个参数是speed,为它赋值100 --><constructor-arg index="0" value="100" /><!-- 构造器的第二个参数是price,为它赋值99999.9 --><constructor-arg index="1" value="99999.9"/>
</bean><bean id="user" class="cn.tewuyiang.pojo.User"><!-- 与上面car的配置同理 --><constructor-arg index="0" value="aaa" /><constructor-arg index="1" value="123" /><constructor-arg index="2" ref="car" />
</bean>

上面就是通过参数的下标为构造器的参数赋值,需要注意的是,参实的下标从0开始。使用上面的方式配置,若赋值的类型与参数的类型不一致,将会在容器初始化bean的时候抛出异常。如果bean存在多个参数数量一样的构造器,Spring容器会自动找到类型匹配的那个进行调用。比如说,Car有如下两个构造器,Spring容器将会调用第二个,因为上面的配置中,index = 1对应的value是double类型,与第二个构造器匹配,而第一个不匹配:

public Car(double price, int speed) {this.speed = speed;this.price = price;
}
// 将使用匹配这个构造器
public Car(int speed, double price) {this.speed = speed;this.price = price;
}

还存在另外一种特殊情况,那就是多个构造器都满足bean的配置,此时选择哪一个?假设当前car的配置是这样的:

<bean id="car" class="cn.tewuyiang.pojo.Car"><!-- 两个下标的value值都是整数 --><constructor-arg index="0" value="100" /><constructor-arg index="1" value="999"/>
</bean>

假设Car还是有上面两个构造器,两个构造器都是一个int类型一个double类型的参数,只是位置不同。而配置中,指定的两个值都是int类型。但是,int类型也可以使用double类型存储,所以上面两个构造器都是匹配的,此时调用哪一个呢?结论就是调用第二个。自己去尝试就会发现,若存在多个构造器匹配bean的定义,Spring容器总是使用最后一个满足条件的构造器。

(三)匹配构造器的参数类型

下面说最后一种匹配方式——匹配构造器的参数类型。直接看配置文件吧:

<bean id="car" class="cn.tewuyiang.pojo.Car"><!-- 使用type属性匹配类型,car的构造器包含两个参数,一个是int类型,一个是double类型 --><constructor-arg type="int" value="100" /><constructor-arg type="double" value="99999.9"/>
</bean><bean id="user" class="cn.tewuyiang.pojo.User"><!-- 对于引用类型,需要使用限定类名 --><constructor-arg type="java.lang.String" value="aaa" /><constructor-arg type="int" value="123" /><constructor-arg type="cn.tewuyiang.pojo.Car" ref="car" />
</bean>

上面应该不难理解,直接通过匹配构造器的参数类型,从而选择一个能够完全匹配的构造器,调用这个构造器完成bean的创建和属性注入。需要注意的是,上面的配置中,类型并不需要按构造器中声明的顺序编写,Spring也能进行匹配。这也就意味着可能出现多个能够匹配的构造器,和上一个例子中一样。比如说,Car还是有下面两个构造器:

public Car(double price, int speed) {// 输出一句话,看是否调用这个构造器System.out.println(111);this.speed = speed;this.price = price;
}
// 将使用匹配这个构造器
public Car(int speed, double price) {// 输出一句话,看是否调用这个构造器System.out.println(222);this.speed = speed;this.price = price;
}

上面两个构造器都是一个int,一个double类型的参数,都符合xml文件中,car这个bean的配置。通过测试发现,Spring容器使用的永远都是最后一个符合条件的构造器,这和上面通过下标匹配是一致的。需要说明的一点是,这三种使用构造器注入的方式,可以混用。

3.静态工厂注入

静态工厂注入就是编写一个静态的工厂方法,这个工厂方法会返回一个需要的值,然后在配置文件中,指定使用这个工厂方法创建bean。首先需要一个静态工厂,如下所示:

public class SimpleFactory {/*** 静态工厂,返回一个Car的实例对象*/public static Car getCar() {return new Car(12345, 5.4321);}
}

下面需要在xml中配置car这个bean,并指定它由工厂方法进行创建。配置如下:

<!-- 注意,这里的配置并不是创建一个SimpleFactory对象,取名为myCar,这一句配置的意思是,调用SimpleFactory的getCar方法,创建一个car实例对象,将这个car对象取名为myCar。
-->
<bean id="car" class="cn.tewuyiang.factory.SimpleFactory" factory-method="getCar"/><bean id="user" class="cn.tewuyiang.pojo.User"><!-- name和age使用set注入 --><property name="name" value="aaa"/><property name="age" value="123"/><!-- 将上面配置的car,注入到user的car属性中 --><property name="car" ref="car"/>
</bean>

以上就配置成功了,测试方法以及执行效果如下,注意看car的属性值,就是在静态工厂中配置的那样,这说明,Spring容器确实是使用定义的静态工厂方法,创建了car这个bean:

@Test
public void test1() {ApplicationContext context =new ClassPathXmlApplicationContext("classpath:applicationContext.xml");// 获取静态工厂创建的carCar car = (Car) context.getBean("car");// 获取userUser user = context.getBean(User.class);System.out.println(car);System.out.println(user);
}

输出如下所示:

Car{speed=12345, price=5.4321}
User{name='aaa', age=123, car=Car{speed=12345, price=5.4321}}

4.实例工厂注入

实例工厂与静态工厂类似,不同的是,静态工厂调用工厂方法不需要先创建工厂类的对象,因为静态方法可以直接通过类调用,所以在上面的配置文件中,并没有声明工厂类的bean。但是,实例工厂,需要有一个实例对象,才能调用它的工厂方法。先看看实例工厂的定义:

public class SimpleFactory {/*** 实例工厂方法,返回一个Car的实例对象*/public Car getCar() {return new Car(12345, 5.4321);}/*** 实例工厂方法,返回一个String*/public String getName() {return "tewuyiang";}/*** 实例工厂方法,返回一个int,在Spring容器中会被包装成Integer*/public int getAge() {return 128;}
}

在上面的工厂类中,共定义了三个工厂方法,分别用来返回user所需的car,name以及age,而配置文件如下:

<!-- 声明实例工厂bean,Spring容器需要先创建一个SimpleFactory对象,才能调用工厂方法 -->
<bean id="factory" class="cn.tewuyiang.factory.SimpleFactory" /><!-- 通过实例工厂的工厂方法,创建三个bean,通过factory-bean指定工厂对象,通过factory-method指定需要调用的工厂方法
-->
<bean id="name" factory-bean="factory" factory-method="getName" />
<bean id="age" factory-bean="factory" factory-method="getAge" />
<bean id="car" factory-bean="factory" factory-method="getCar" /><bean id="user" class="cn.tewuyiang.pojo.User"><!-- 将上面通过实例工厂方法创建的bean,注入到user中 --><property name="name" ref="name"/><property name="age" ref="age"/><property name="car" ref="car"/>
</bean>

尝试从Spring容器中取出name,age,car以及user,看看它们的值,测试代码如下:

@Test
public void test1() {ApplicationContext context =new ClassPathXmlApplicationContext("classpath:applicationContext.xml");// 获取静态工厂创建的car,name和age这三个beanCar car = (Car) context.getBean("car");String name = (String) context.getBean("name");Integer age = (Integer) context.getBean("age");// 获取user这个beanUser user = context.getBean(User.class);System.out.println(car);System.out.println(name);System.out.println(age);System.out.println(user);
}

以下就是输出结果,可以看到,通过工厂创建的bean,都在Spring容器中能够获取到:

Car{speed=12345, price=5.4321}
tewuyiang
128
User{name='tewuyiang', age=128, car=Car{speed=12345, price=5.4321}}

Bean的四种注入方式相关推荐

  1. Spring的四种注入方式

    Spring的四种注入方式 1.set方法注入 2.构造器注入 3.静态工厂注入 4.实例工厂注入 我使用下面两个类来进行注入的演示,这两个类分别是User和Car类: Car类: public cl ...

  2. Spring Bean四种注入方式(Springboot环境)

    阅读此文建议参考本人写的Spring常用注解:https://blog.csdn.net/21aspnet/article/details/104042826 给容器中注册组件的四种方法:  1.@C ...

  3. Spring bean的三种注入方式

    Spring的一个重要原理就是IOC(Inverse Of Control),即控制反转.IOC就是一种将组件依赖关系的创建和管理置于程序外部的技术,在Spring中Bean组件的实例化和依赖关系的管 ...

  4. spring中bean的两种注入方式

    一是依赖注入(构造方法) 二是set注入(属性的set方法) 转载于:https://www.cnblogs.com/l-x-x-y-d-j/p/11355137.html

  5. spring入门之Spring 常用的三种注入方式

    Spring 常用的三种注入方式 Spring 通过 DI(依赖注入)实现 IOC(控制反转),常用的注入方式主要有三种:构造方法注入,set 方法注入,基于注解的注入. 一.通过构造方法注入 先简单 ...

  6. Spring 依赖注入的理解及三种注入方式

    Spring 依赖注入概念和三种注入方式(理解及应用) 什么是注入 要了解Spring的三种注入方式首先前提是得先了解一下什么是注入,相信很多人对这个概念都是模糊不清的,网上的解释是这样的: 依赖注入 ...

  7. @Resource,@Autowired,@Inject3种注入方式详解

    转载自 @Resource,@Autowired,@Inject3种注入方式详解 概况 @Resource,@Autowired,@Inject 这3种都是用来注入bean的,它们属于不同的程序中. ...

  8. tp5类的属性不存在_thinkPHP5.1框架中Request类四种调用方式示例

    本文实例讲述了thinkPHP5.1框架中Request类四种调用方式.分享给大家供大家参考,具体如下: 1. 传统调用 访问方式:http://127.0.0.1/demo/demo3/test?n ...

  9. spring三种注入方式

    设置Spring的作用域 或者使用枚举值设置 单例和多里使用场景 自动注入 @Primary 一个接口有多个实现被spring管理吗,在依赖注入式,spring会不知道注入哪个实现类就会抛出NoUni ...

最新文章

  1. 一步一步深入理解Dijkstra算法
  2. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)
  3. 正则表达式匹配中文字符串的文章URL
  4. ac automaton 专题
  5. Dubbo的Javassist代理
  6. Java高并发编程详解系列-Java线程入门
  7. 吴恩达 深度学习 编程作业(2-1.1) Initialization
  8. 一个简单字符型设备驱动及其测试
  9. springboot 请求路径有后缀_SpringBoot中配置Web静态资源路径的方法
  10. GoJS图表组件简介
  11. Centos 7 修改 Mysql 5.7 默认端口号
  12. 如何将照片中的文字转变成可编辑的文章(如何将书上的文字转变为可编辑的文字)
  13. 选择粘贴性无html,office无法复制粘贴-Word把内容从一个文档选择性粘贴到另一个文档,具体操作方法...
  14. 谁再说“游戏没用”,就拿这个回怼他!
  15. 申请德国农工大学计算机案例,德州农工大学本科案例
  16. 讯飞 AIUI 集成
  17. 人工智能会代替人工翻译?知行翻译:这是不可能地!
  18. vue element上传额外参数
  19. Typora 未保存文件找回
  20. 关于nignx老是报错404的问题

热门文章

  1. 【HCIA】实验笔记-VLAN
  2. 华为交换机:本征VLAN
  3. 让卡巴斯基7.0支持Windows2003
  4. 支持m2的主板换m2硬盘无法识别的问题,主板:七彩虹H410-T
  5. 微信开发者工具 / 反编译工具CrackMinApp 下载安装
  6. linux怎么安装useradd命令,Linux下useradd命令
  7. MIT推出新一代机器人猎豹3,可用于灾害救援
  8. 简单理解高内聚低耦合-高内聚低耦合通俗理解是什么?
  9. Android App安装包瘦身计划
  10. java计算机毕业设计高速收费系统后台源程序+mysql+系统+lw文档+远程调试