由于Spring是用于管理Java Bean对象,也就是Spring中装载很多JavaBean对象,就形象的将Spring称为Java Bean容器,简称 Spring容器。
依赖注入:指将一个计算过程需要用到的资源注入到合适的位置。
依赖:一个计算过程需要的前提条件。
举个例子:
计算圆形面积?PI * r * r PI是常数,根据计算公式,r是计算园面积的前提条件,可以称为:计算园面积依赖于半径r。
光头强砍树这个事情,需要依赖于“斧子”。
依赖注入:
计算园面积时候,将半径交给公式,就是依赖注入
光头强砍树之前,将斧子交给他,就是依赖注入
Spring Bean 容器提供JavaBean的依赖注入功能,会根据类型或者BeanID将JavaBean注入到合适位置,使程序运行能够得到合适前提依赖对象。
代码:
锯子
package cn.yemao.spring02;
import java.io.Serializable;
/**
* 斧子类型
*/
public class Axe implements Serializable {
private String name = "开天斧";
@Override
public String toString() {
return name;
}
工人
package cn.yemao.spring02;
import java.io.Serializable;
public class Worker implements Serializable {
private String name = "光头强";
private Axe axe;
/**
* work:工作
* 这个方法体现了:光头强工作时候依赖于斧子对象!
*/
public void wrok(){
//字符串连接时候,会自动调用对象的 toString() 然后连接起来
System.out.println(name + "使用" + axe + "砍树");
}
public void setAxe(Axe axe) {
this.axe = axe;
}
public Axe getAxe() {
return axe;
}
}
配置类
package cn.yemao.config;
import cn.tedu.spring02.Axe;
import cn.tedu.spring02.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean //BeanID = axe
public Axe axe(){
return new Axe();
}
/**
* 利用方法参数注入 axe 对象
* Spring 在运行期间会根据参数的类型自动匹配找到axe对象注入到方法参数
* @param axe2
* @return
*/
@Bean
public Worker worker(Axe a){
Worker worker = new Worker();
worker.setAxe(a);
return worker;
}
}
测试案例
package cn.yemao;
import cn.tedu.config.Config;
import cn.tedu.spring02.Worker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestCase {
AnnotationConfigApplicationContext ctx;
@Before
public void init(){
ctx = new AnnotationConfigApplicationContext(Config.class);
}
@After
public void destroy(){
ctx.close();
}
@Test
public void worker(){
Worker worker = ctx.getBean(Worker.class);
//测试结果中出现 开天斧 字样说明注入成功。
worker.wrok();
}
}
首先按照类型自动匹配:
首先根据注入参数的类型(Axe)在Spring容器中寻找类型相同的唯一Bean对象,如果没有找到类型一致的对象,就抛出异常!
如果找到唯一的Axe类型对象,就注入成功。
如果匹配到Axe类型多个对象,就按照BeanID进行匹配
然后按照BeanID进行匹配:
根据变量名和BeanID一致规则进行匹配,如果匹配到唯一的一个Bean对象,就注入成功
否则如果没有匹配到BeanID名称一致的对象就注入失败,抛出异常。
案例,根据名字匹配:
配置类:
package cn.yemao.config;
import cn.tedu.spring02.Axe;
import cn.tedu.spring02.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean //BeanID = axe
public Axe axe(){
return new Axe();
}
@Bean //BeanID = axe2
public Axe axe2(){
return new Axe();
}
/**
* 利用方法参数注入 axe 对象
* Spring 在运行期间会根据参数的类型自动匹配找到axe对象注入到方法参数
* @param axe2
* @return
*/
@Bean
public Worker worker(Axe axe2){
Worker worker = new Worker();
worker.setAxe(axe2);
return worker;
}
}
测试
@Test
public void worker(){
Worker worker = ctx.getBean(Worker.class);
//测试结果中出现 开天斧 字样说明注入成功。
worker.wrok();
}
@Autowired Spring 提供的注解
@Resource Java提供的注解,Spring支持其功能
可以标注在 属性和set方法上,Spring会提供自动注入功能
组件扫描时候自动工作
注入原理:
案例:
笔类:
package cn.yemao.spring02;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@Component
public class Pen implements Serializable {
private String name = "万宝龙";
@Override
public String toString() {
return name;
}
}
人
package cn.yemao.spring02;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@Component
public class Person implements Serializable {
private String name = "小明";
//Spring 会自动从容器中找到pen对象注入到pen变量中
@Autowired
private Pen pen;
public void write(){
System.out.println(name+"使用"+pen+"写字");
}
public Pen getPen() {
return pen;
}
public void setPen(Pen pen) {
this.pen = pen;
}
}
配置
@Configuration
@ComponentScan("cn.tedu.spring02")
public class Config {
//...
}
测试:
@Test
public void person(){
Person person = ctx.getBean(Person.class);
person.write();
}
@Autowired 注解可以标注在属性上,也可以标注在 set方法上,都可以完成属性注入。
@Component
public class Person implements Serializable {
private String name = "小明";
//Spring 会自动从容器中找到pen对象注入到pen变量中
//@Autowired //标注在属性上,Spring会注入属性
private Pen pen;
public void write(){
System.out.println(name+"使用"+pen+"写字");
}
public Pen getPen() {
return pen;
}
@Autowired //Spring 会自动调用set方法注入属性
public void setPen(Pen pen) {
System.out.println("调用了setPen()");
this.pen = pen;
}
}
@Autowired 注解可以标注在构造器上,完成属性注入。
@Component
public class Person implements Serializable {
private String name = "小明";
private Pen pen;
public Person(){}
@Autowried
public Person(Pen pen){
System.out.println("调用Person(pen)");
this.pen = pen;
}
public void write(){
System.out.println(name+"使用"+pen+"写字");
}
public Pen getPen() {
return pen;
}
public void setPen(Pen pen) {
System.out.println("调用了setPen()");
this.pen = pen;
}
}
3种方式的运算结果一样,基本上可以相互替代
早期 Spring2/Spring3 建议使用 set方法注入
Spring4 时代,大多使用 属性 注入,这种方式因为不用写 set方法和构造器方法,使用简洁方便
Spring5 时代,推荐使用 构造器注入和set方法注入,不建议使用 属性注入
Spring5 中 @Autowried 属性注入时候,会出现不建议使用的提醒!
由于 属性注入代码编写真的太方便了,所以目前仍然广为使用!!!
###@Autowired 和 @Resource 的区别
@Autowired 注入时候,先按照参数类型和Bean类型一致的规则进行匹配,如果没有匹配到唯一的Bean对象,在按照属性名和BeanID一致的规则进行匹配。
大致理解:先按照类型匹配,再按照BeanID匹配
@Resource 先按照属性名和BeanID一致的规则进行查询,如果找到唯一的一个Bean对象再检查类型,如果类型也一致就注入成功否则抛出异常。如果按照BeanID匹配没有找到唯一的Bean对象,再按照参数类型寻找唯一的对象,找到就注入,找不到就抛出错误
大致理解:先按照BeanID匹配,再按照Bean的类型匹配
如果不严格区别,其最终效果是一样的!
@Resource 不能写在构造器上!
###
联系客服