Spring学习笔记1—依赖注入(构造器注入、set注入和注解注入)
什么是依赖注入
在以前的java开发中,某个类中需要依赖其它类的方法时,通常是new一个依赖类再调用类实例的方法,这种方法耦合度太高并且不容易测试,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。
依赖注入的方式
依赖注入有3种方式:构造器注入、set注入和注解注入。
1.构造器注入
构造器注入保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用。
使用方式:
- 在类中,不用为属性设置setter方法,但是需要生成该类带参的构造方法。
- 在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了<constructor-arg>节点,该节点有四个属性
- index:指定注入属性的顺序索引,从0开始;
- type:指该属性所对应的类型;
- ref:引用的依赖对象;
- value:当注入的不是依赖对象,而是基本数据类型时,就用value;
例子1:
public class SpringAction {
//注入对象springDao
private SpringDao springDao;
private User user; public SpringAction(SpringDao springDao,User user){
this.springDao = springDao;
this.user = user;
System.out.println("构造方法调用springDao和user");
} public void save(){
user.setName("卡卡");
springDao.save(user);
}
}
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
<constructor-arg index="0" ref="springDao"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
<bean name="user" class="com.bless.springdemo.vo.User"></bean>
其中index属性表示注入的bean在构造方法中的参数顺序。
例子2:
有时需要联合使用type和index才能确定匹配项和构造函数入参的对应关系,看下面的代码。
public Car(String brand, String corp,double price){
this.brand=brand;
this.corp=corp;
this.price=price;
} public Car(String brand, String corp,int maxSpeed){
this.brand=brand;
this.corp=corp;
this.maxSpeed=maxSpeed;
}
这里,Car拥有两个重载的构造函数,它们都有三个入参。针对这种情况,按照入参索引的配置方式又难以满足要求了,这时需要联合使用<constructor-arg>的type和index才能解决问题
<!-- 构造函数注入(通过入参类型和位置索引确定对应关系) -->
<!-- 对应public Car(String brand, String corp,int maxSpeed)构造函数 -->
<bean id="car3" class="com.spring.model.Car">
<constructor-arg index="0" type="java.lang.String" value="奔驰"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="中国一汽"></constructor-arg>
<constructor-arg index="2" type="int" value="200"></constructor-arg>
</bean>
对于由于参数数目相同而类型不同所引起的潜在配置歧义问题,Spring容器可以正确启动且不会给出报错信息,它将随机采用一个匹配的构造函数实例化Bean,而被选择的构造函数可能并不是用户所希望的。因此,必须特别谨慎,以避免潜在的错误。
2.set注入
set注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。
Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
假设Bean显示定义了一个带参的构造函数,则需要同时提供一个默认无参的构造函数,否则使用属性注入时将抛出异常。
例子1:
package com.bless.springdemo.action;
public class SpringAction {
//注入对象springDao
private SpringDao springDao;
//一定要写被注入对象的set方法
public void setSpringDao(SpringDao springDao) {
this.springDao = springDao;
} public void ok(){
springDao.ok();
}
}
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(1)依赖注入,配置当前类中相应的属性-->
<property name="springDao" ref="springDao"></property>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
这里不再使用“constructor-arg”而是使用“property”属性。
3.注解注入
注解注入其实是使用注解的方式进行构造器注入或者set注入。
spring2.5开始提供了基于注解(Annotation-based)的配置,我们可以通过注解的方式来完成注入依赖。在Java代码中可以使用 @Resource或者@Autowired注解方式来经行注入。
虽然@Resource和@Autowired都可以来完成注入依赖,但它们之间是有区别的:
- @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;
- @Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;
- @Resource注解是又J2EE提供,而@Autowired是由Spring提供;
例子:
package com.bless.springdemo.action;
public class SpringAction {
//注入对象springDao
@Resource
private SpringDao springDao;
//不需要要写被注入对象的set方法,spring会帮你get/set public void ok(){
springDao.ok();
}
}
<context:annotation-config/> <bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--不需要配置属性,@Resource默认按照名称装配注入-->
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
<context:annotation-config/>的作用是开启注解。
@Autowired的同理,只不过默认是按照类型装配注入。
补充:
@Autowired 可以对成员变量、方法以及构造函数进行注释。那么对成员变量和构造函数进行注释又有什么区别呢?
先来看下面一段代码:
@Autowired
private User user;
private String school; public UserAccountServiceImpl(){
this.school = user.getSchool();
}
这段代码执行会报错,因为Java类会先执行构造方法,然后再给注解了@Autowired 的user注入值,所以在执行构造方法的时候,就会报错。
解决办法是,使用构造器注入,如下:
private User user;
private String school; @Autowired
public UserAccountServiceImpl(User user){
this.user = user;
this.school = user.getSchool();
}
参考:
Spring学习笔记1—依赖注入(构造器注入、set注入和注解注入)的更多相关文章
- Spring学习笔记之依赖的注解(2)
Spring学习笔记之依赖的注解(2) 1.0 注解,不能单独存在,是Java中的一种类型 1.1 写注解 1.2 注解反射 2.0 spring的注解 spring的 @Controller@Com ...
- Java框架spring 学习笔记(十九):事务管理(注解管理)
注解管理的方式要比xml配置方式要简单很多 只需在配置文件中添加事务注解 <?xml version="1.0" encoding="UTF-8"?> ...
- SpringMVC:学习笔记(11)——依赖注入与@Autowired
SpringMVC:学习笔记(11)——依赖注入与@Autowired 使用@Autowired 从Spring2.5开始,它引入了一种全新的依赖注入方式,即通过@Autowired注解.这个注解允许 ...
- Spring学习笔记(七)模拟实际开发过程的调用过程XML版-Setter方式注入
模拟实际开发过程的调用过程XML版-Setter方式注入 源码获取github [TOC] 1.项目结构 2.jar包跟上个一样 3.重写set方法 UserServiceImpl.java 1234 ...
- [跟我学spring学习笔记][DI循环依赖]
循环依赖 什么是循环依赖? 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方. Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢? ...
- 不错的Spring学习笔记(转)
Spring学习笔记(1)----简单的实例 --------------------------------- 首先需要准备Spring包,可从官方网站上下载. 下载解压后,必须的两个包是s ...
- spring学习笔记(一) Spring概述
博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书. 强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...
- Spring学习笔记(六)—— SSH整合
一.整合原理 二.整合步骤 2.1 导包 [hibernate] hibernate/lib/required hibernate/lib/jpa 数据库驱动 [struts2] struts-bla ...
- Java架构师之路 Spring学习笔记(一) Spring介绍
前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...
随机推荐
- Linux系统中磁盘block和windos中的簇一个意思
block就是几个连续扇区组成一个block,每个分区可以设置block大小,好比一个txt只有2字节,但是这个分区的block为4K,那么其实这个txt需要4k来存储(所以大文件block设置大比较 ...
- codeforces Round #Pi (div.2) 567ABCD
567A Lineland Mail题意:一些城市在一个x轴上,他们之间非常喜欢写信交流.送信的费用就是两个城市之间的距离,问每个城市写一封信给其它城市所花费的最小费用和最大的费用. 没什么好说的.直 ...
- leetCode 30.Substring with Concatenation of All Words (words中全部子串相连) 解题思路和方法
Substring with Concatenation of All Words You are given a string, s, and a list of words, words, tha ...
- script 标签里的 async 和 defer
无 async 和 defer 浏览器立即加载并执行指定脚本(读到即加载并执行),阻塞文档解析 async 脚本的加载执行和文档的加载渲染 并行. defer 脚本的加载和文档的加载渲染并行,但脚本的 ...
- 各类 HTTP 返回状态代码详解(转)
FTP状态码 一.HTTP状态码 如果某项请求发送到您的服务器要求显示您网站上的某个网页(例如,用户通过浏览器访问您的网页或 Googlebot 抓取网页时),服务器将会返回 HTTP 状态代码以响应 ...
- IRQ与FIQ的区别
1.对FIQ你必须进快处理中断请求,并离开这个模式. 2.IRQ可以被FIQ所中断,但FIQ不能被IRQ所中断,在处理FIQ时必须要关闭中断. 3.FIQ的优先级比IRQ高. 4.FIQ模式下,比IR ...
- Linux Linux程序练习二
/* 编写一个程序读取a.txt文件,将文件内容数字从小到大排序,并将排序结果写入b.txt. */ #include <stdio.h> #include <stdlib.h> ...
- <head> 或 <body> 中的 JavaScript
您可以在 HTML 文档中放入不限数量的脚本. 脚本可位于 HTML 的 <body> 或 <head> 部分中,或者同时存在于两个部分中. 通常的做法是把函数放入 <h ...
- asp.net c#采集需要登录页面的实现原理及代码
当我们采集页面的时候,如果被采集的网站需要登录才能采集,原理搞清楚了,就好办了,我们所要做的仅仅是在采集的时候(或者说HttpWebRequest提交数据的时候),将Cookie信息放入Http请求头 ...
- Android-ViewPagerIndicator框架使用——TabPageIndicator
前言:TabPageIndicator这个类和之前的不大一样,他不仅提供了展示的功能,而且可以点击,下面的viewpager可以跳转的有点tabhost的感觉. 一:布局文件的定义,simple_ta ...