Spring IOC容器提供了依赖注入功能,可以将一个组件依赖的对象,在使用之前注入到合适位置.比如,如下关系模拟了光头强砍树时依赖电锯.
Spring IOC 解决依赖注入,在配置类Config中为Bean组件初始化方法增加参数,Spring IOC 容器会在初始化时,自动根据类型注入Bean组件对象,解决"依赖注入"问题:
第一步:新创建spring2工程,pom文件添加依赖
org.springframework
spring-context
5.2.2.RELEASE
junit
junit
4.13
test
javax.annotation
javax.annotation-api
1.3.2
第二步: 分别在demo包下创建工具类和工人类,
package cn.tedu.demo;
import java.io.Serializable;
public class Saw implements Serializable {
private String name = "寒冰锯";
@Override
public String toString() {
return name;
}
}
package cn.tedu.demo;
import java.io.Serializable;
public class Worker implements Serializable {
private String name = "光头强";
public Saw saw;
public void work(){
System.out.println(name+"使用"+saw+"砍树");
}
}
第三步:编辑配置类,使用@Bean依赖注入,是两者产生联系
package cn.tedu.context;
import cn.tedu.demo.Saw;
import cn.tedu.demo.Worker;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
@Bean
public Saw saw(){
return new Saw();
}
/*Spring 会自动根据变量类型匹配Bean组件的类型
* 若匹配成功,就将Bean组件注入到方法参数中*/
@Bean
public Worker worker(Saw s){//参数类型要匹配正确
Worker worker = new Worker();
worker.saw=s;
return worker;
}
}
第四步:test包下创建测试类,控制台查看结果
package cn.tedu.test;
import cn.tedu.context.Config;
import cn.tedu.demo.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 testWorker(){
Worker worker = ctx.getBean("worker", Worker.class);
worker.work();//光头强使用寒冰锯砍树
}
}
Spring 提供的组件扫描功能,在扫描时也可以完成依赖注入,这样可以减少编码提高编程效率
如何使用@Autowired?注入到对象属性上和注入到set方法上,看情况使用!!!
以下练习注入到对象属性上:
第一步:创建新工程spring03,复制spring2的src包,分别编辑工具类和工人类,配置类添加包扫描组件
第二步:测试类不变,进行测试,结果还是一样,所以,添加组件扫描和依赖注入,能够减少代码并提高编程效率
@Autowired注入到set方法上:具有一定的逻辑
第一步:其他都不变,编辑worker类
第二步:进行测试set方法注入的效果:
第一步:创建新项目spring4,编辑pom.xml文件添加版本依赖
org.springframework
spring-context
5.2.2.RELEASE
junit
junit
4.13
test
javax.annotation
javax.annotation-api
1.3.2
第二步:cn.tedu.demo包下创建Tool工具接口
package cn.tedu.demo;
/*抽象的工具类型*/
public interface Tool {
}
第三步:创建工人类,电锯类和斧子类
package cn.tedu.demo;
import org.springframework.stereotype.Component;
@Component//组件扫描,交给spring创建对象
public class Axe implements Tool{
private String name = "开天斧";
@Override
public String toString() {
return name;
}
}
package cn.tedu.demo;
//没有加组件扫描,就不会被spring创建对象
public class Saw implements Tool{
private String name="寒冰锯";
@Override
public String toString() {
return name;
}
}
package cn.tedu.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Worker implements Serializable{
private String name= "光头强";
@Autowired//接口的依赖注入
private Tool tool;
public void work(){
System.out.println(tool);
System.out.println(tool == null);
System.out.println(name+"使用"+tool+"砍树");
}
}
第四步:创建配置类,用于扫描包
package cn.tedu.context;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("cn.tedu.demo")//配置类扫描包,spring为其包下的类创建对象
public class Config {
}
第五步:创建测试类:
package cn.tedu.test;
import cn.tedu.context.Config;
import cn.tedu.demo.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 testWorker(){
Worker worker = ctx.getBean("worker", Worker.class);
worker.work();
}
}
控制台:
第六步:如果想使用电锯类,就要把@Component添加到电锯类上,去掉斧子类的@Component组件扫描
第七步:测试
当电锯类和斧子类都加了@Component组件扫描时:
第一步:如果使用斧子类,就自定义组件ID,使其能被识别
测试结果:
第二步:如果使用电锯类,自定义组件ID,注意,斧子类上的自定义组件ID就要删除
测试结果:
假如想使用电锯,就要在依赖注入接口再添加@Qualifier("saw"),指定使用电锯对象
同样,想使用斧子,就要在依赖注入接口再添加@Qualifier("axe"),指定使用斧子对象
这两种方案能解决冲突,但实际开发当中用处并不多,而是尽量采用类型注入,默认值注入等更方便的方法,保证每个一个组件都有唯一的名字