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