Spring——DI和通过注解实现IOC和DI

Fiorenza ·
更新时间:2024-09-20
· 948 次阅读

DI(依赖注入)

- 问题的提出:
之前所说的IOC,其中没有提到,如果当spring保存的类中有其他属性需要赋值的话怎么办(其实可以用工厂模式来完成),所以今天我们就来解决这个问题。
- DI的概念:
当spring容器创建对象的时候,通过xml配置文件,把需要赋值的JavaBean属性设置在配置文件中,这样就可以把值赋到了对应的属性上。
- 成员属性和JavaBean属性:
JavaBean属性=成员属性吗?答案是否定的,成员属性是在类里的,而JavaBean属性则是由类中的成员属性是否有set方法决定的,这里后面通过代码再进行解释。
- 注入方法1——set注入
注入普通属性:
配置文件中,通过name属性关联上类中的setXXX()方法,value中填入需要保存的值,配置文件代码如下。

a1 a2 b1 b2

从上述代码可以看到如何通过配置文件,注入属性给对应的属性,这里做几点说明, 标签中的name属性,对应的是类中的setXXX()方法中的xxx,该属性也可以称为JavaBean属性,如类中有setAge()方法,则name=“age”,绑定到的就是该方法。

注入自定义属性:
当需要注入的属性中,包含对象这种自定义的属性,则注入方式和上述普通属性就有所区别,代码如下。
在这里插入图片描述
和普通属性注入的区别是,不使用value属性,取而代之的是ref属性,该属性里写的是另一个bean的id,其中这个新声明的bean则是自定义属性。
自定义属性注入的自动装配:
自动装配的两种方法:
byName和byType,前者是根据javabean中需要注入的属性的名字 ,在spring容器中找对应id的将该的对象复制给 当前的属性,后者根据javabean中需要注入的属性的类型,在spring容器中找对应class类型的将该的对象复制给当前的属性。
关键字为:autowrite=” ? “
自动装配的两种范围:
指定bean进行关键字声明,只有该bean自动装配
把关键字写再beans下,全部bean都实行自动装配
代码如下:

//指定bean自动装配 <bean id="teacher" class="cn.tedu.beans.Teacher" autowire="byName //全局默认自动装配 注入方法2——基于构造方法的注入
上述方法1,是基于有无参构造方法,当程序里have有参构造的时候,就可以使用该方法,该方法很简单,只用修改xml配置文件即可,代码如下。

constructor-arg是标签关键字,在bean中写上这个标签,则说明使用基于构造方法的注入,当spring开始解读xml文件读到这句话的时候,就自动使用构造方法注入。
参数解释:
index:为构造方法的第几个参数 进行配置
name:为构造方法的哪个名字的参数进行配置
type:该构造方法参数的类型
value:该构造方法参数的值 ,用来指定基本值
ref:该构造方法参数的值,用来指定引用其他bean的值
注意:index 和 name 可以配置任何一个或同时配置 但要求一旦配置必须正确,推荐优先使用index方式配置 防止没有源码造成name无法匹配到对应参数

通过使用注解实现IOC

引入:
之前我们已经说过,IOC就是把创建对象和销毁对象的工作交给spring来完成,这之中有很大的工作量都是在配置xml文件上,如果项目足够大,可能xml里会有成千上万个bean,修改起来真的很浪费时间,所以由此就产生了新的技术——注解。

注解实现IOC:
类中的代码: public class user { @Value("${name}") private String name; private List list; private Set set; private Map map; private dog dog; ..........

这一块我只注入了name属性,因为集合和自定义属性需要其他方式来注入,善于观察的小伙伴应该已经发现,我这里的value里,写法似乎有些奇怪,这是因为我把属性的值放入了properties文件中,直接从文件中获取,这样以后修改代码的时候,就只用修改properties,而不用修改代码。

注入集合:
集合的注入和注入普通属性有些区别但是过程和上面流程图一样。首先在xml配置文件中通过util名称空间来初始化集合数据,接着通过@value("#{@s1}")来类中绑定变量,其中s1是自定义的名字。代码如下:

//xml配置文件中 a1 a2 //类中 public class user { @Value("${name}") private String name; @Value("#{@l1}") private List list; private Set set; @Value("#{@m1}") private Map map; private dog dog; .........

注入自定义属性
在类中自定义属性上添加@Autowired和@Qulifier,则spring在读取到该注解时,则知道这是一个自定义属性类型,然后开始在spring容器中开始寻找该自定义属性,寻找方式如下:

同时配置了@Autowired和@Qulifier:
则直接按照指定id(如果不指定则用变量名作为id)寻找bean,找到就注入,找不到抛出异常

如果只配置了@Autowired:
则先按照类型匹配,如果找到唯一的,注入
如果找不到或找到多个,则开始按照id注入
按照id寻找,如果找到唯一的注入,找不到就抛出异常

代码如下:

public class user { @Value("${name}") private String name; @Value("#{@l1}") private List list; private Set set; @Value("#{@m1}") private Map map; @Autowired @Qualifier("dog")//直接按照ID为dog,开始寻找spring中的bean。如果不写@Qualifer,则按照dog类型去寻找 private dog dog; ....... //dog类 @Component("dog") public class dog { @Value("cc") private String name; ....... 其他注解

1.@Scope(value=“prototype”)
用来确定该bean是单例还是多例

@Component @Scope("prototype") public class Teacher { }

2.@Lazy
确实该bean是否是懒加载机制

@Component @Lazy public class Teacher { }

3.@PostConstruct和 @PreDestroy
修饰bean中的方法,分别是初始化方法和销毁方法,创建对象时自动调用

@Component public class Dog { @PostConstruct public void init(){ System.out.println("Dog的初始化方法。。。"); } @PreDestroy public void destory(){ System.out.println("Dog的销毁方法。。。"); } }

4.@Controller @Service @Repository @Component
这四个功能完全相同,都是用来修饰类的,修饰过的就成为了bean,被spring管理。

其中@Component一般认为是通用的注解

而@Controller用在软件分层中的控制层,一般用在web层

而@Service用在软件分层中的业务访问层,一般用在service层

而@Repository用在软件分层中的数据访问层,一般用在dao层

牛像话 原创文章 4获赞 4访问量 260 关注 私信 展开阅读全文
作者:牛像话



DI 注解 spring ioc

需要 登录 后方可回复, 如果你还没有账号请 注册新账号