Spring思想注入依赖学习笔记.docx
- 文档编号:6799182
- 上传时间:2023-01-10
- 格式:DOCX
- 页数:23
- 大小:29.21KB
Spring思想注入依赖学习笔记.docx
《Spring思想注入依赖学习笔记.docx》由会员分享,可在线阅读,更多相关《Spring思想注入依赖学习笔记.docx(23页珍藏版)》请在冰豆网上搜索。
Spring思想注入依赖学习笔记
本人总结了一些ssh常见的面试题例举如下
强调在回答的时候不要光回答概念,要思维扩散性的讲些相关的东西
spring的优点?
1.降低了组件之间的耦合性,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部
什么是DI机制?
依赖注入(DependecyInjection)和控制反转(InversionofControl)是同一个概念,具体的讲:
当某个角色
需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。
但在spring中
创建被调用者的工作不再由调用者来完成,因此称为控制反转。
创建被调用者的工作由spring来完成,然后注入调用者
因此也称为依赖注入。
spring以动态灵活的方式来管理对象,注入的两种方式,设置注入和构造注入。
设置注入的优点:
直观,自然
构造注入的优点:
可以在构造器中决定依赖关系的顺序。
什么是AOP?
面向切面编程(AOP)完善spring的依赖注入(DI),面向切面编程在spring中主要表现为两个方面
1.面向切面编程提供声明式事务管理
2.spring支持用户自定义的切面
面向切面编程(aop)是对面向对象编程(oop)的补充,
面向对象编程将程序分解成各个层次的对象,面向切面编程将程序运行过程分解成各个切面。
AOP从程序运行角度考虑程序的结构,提取业务处理过程的切面,oop是静态的抽象,aop是动态的抽象,
是对应用执行过程中的步骤进行抽象,,从而获得步骤之间的逻辑划分。
aop框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
依赖注入(DI)
依赖注入(DI),是spring容器实现的基础,在spring-core模块中实现的。
所谓DI,就是指对象是被动接受依赖类而不是自己主动去找,换句话说就是指对象不是从容器中查找它依赖的类,而是在容器实例化对象的时候主动将它依赖的类注入给它。
下面举一个形象的例子:
1.class B{
2. private A a;
3. public void setA(A a){
4. this.a=a;
5. }
6.}
7.
8.class A{
9.}
显然,此时B是依赖与A。
我们不妨将A比作牛,将B比作人,人吃牛是显然的事实。
当用户要利用B的时候,必须先要指定他所依赖的A的对象。
这样代码模块之间就具有很强的耦合。
通过依赖注入的方式,能够使B对A的依赖关系对代码人员变得松散。
我们将A和B对象都交给容器来管理,通过配置文件告诉B该依赖的A,这样代码中的依赖关系被移到了配置文件中,通过对配置文件的管理,很容易编写低耦合的代码。
对于依赖注入的几种实现参考DependencyInjection。
但是,目前在学术界争论的焦点在于:
DI究竟能不能给程序带来解耦。
众所周知,封装和依赖是面向对象编程思想中两个很重要的概念。
编写高内聚低耦合的代码是OOP编程的目标。
但是,这其中本来就存在着互相矛盾。
所谓高内聚,就是通过封装之后,是被封装的各个模块(这里一般是一个类)内部的功能功能相关性、依赖性、协作性等高。
此时,我们要做的就是对模块按照上述标准进行分解,直到满意为止。
但是,什么时候才是一个尽头?
当我们在不断的对模块进行分解时,被分解的模块之间的耦合就不断的增强。
此时,我们就会反过来想,低耦合就是不断降低模块之间的关系,没有关系最好。
于是我们要做的就是模块合组,将耦合关系强的模块组合在一起。
那怎么样才能做到最好?
那不就是用一个统一的模块来表示整个需要描述的系统,废话那不就等于什么都没有做。
说了这么多,我要说的就是要在内聚和耦合之间进行权衡,找到一个恰当的平衡点。
下面切入正题,所谓耦合,简单的理解就是模块与模块之间的关系,最主要的就是依赖关系。
从上面的讨论很容易的发现模块之间的耦合是无法消除的,除非他们之间没有任何关系。
那么DI为什么声称能够给程序带来解耦呢?
我觉耦合并没有消除,甚至没有减弱。
DI只是将耦合进行了转移,通常是转移到配置文件中。
B对A的依赖关系原来在这里。
因此,在主程序中的不再为newB的时候为A所扰心。
但是,如果我们从另外一个方面来考虑,如果我们把A和B当作两个由第三方编写代码模块,我们无法修改他的源代码。
我们会发现,DI的机制就变得非常有用了。
我们只需要根据需要写配置文件,告诉B所依赖的模块A到底是那个A。
当A公司对A进行升级时,直接将组件进行替换;或者当我们改用C公司的模块C时,要做的只是告诉B所依赖的模块A是C公司的那个模块。
这种对耦合转移的方式,在实际软件开发,尤其是基于组件或插件的开发中,意义非凡。
其实,回头想想我们怎么能够既要求模块之间协作又要求没有耦合呢。
DI只不过是将各个开发人员之间代码的耦合转移到统一管理的地方。
但是,当系统比较大的时候,配置文件会被胀的很大,给配置编写带来了一定的难度,目前能够做的只是根据配置的bean的不同类别,将配置文件分块。
目前,貌似spring中增加了注解的功能。
我个人觉得,注解的方式,确实给程序员带来了不少方便,他就相当于一部傻瓜相机,拍照的参数由相机自己来调,但是也会给开发带来一些隐含的问题。
注入依赖
依赖注入(DI)的基本原理是对象之间的依赖,通过以下几种方式实现:
构造器的参数、工厂方法的参数,或给由构造函数或者工厂方法创建的对象设置属性。
容器的工作就是创建bean时注入那些依赖关系,这样相对由bean自己来完成这些工作从控制上发生了根本性的倒转,因此依赖注入也叫控制反转(IoC)。
DI注入有Setter和构造器两种注入方式。
构造器注入:
通过带参数的构造器实现,每个参数就是一个依赖。
也可以通过静态工厂方法来传参数,但两者是类似的,
先来看下只使用构造器参数来注入依赖关系的例子:
Java代码
1.public class SimpleMovieLister {
2.
3. //依赖于MovieFinder
4.
5. private MovieFinder movieFinder;
6.
7. //注入到构造器中
8.
9. public SimpleMovieLister(MovieFinder movieFinder) {
10.
11. this.movieFinder = movieFinder;
12.
13. }
14.
15.}
publicclassSimpleMovieLister{
//依赖于MovieFinder
privateMovieFindermovieFinder;
//注入到构造器中
publicSimpleMovieLister(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
}
构造器参数解析:
根据参数类型来匹配,若参数类型定义明确,则bean实例化时根据参数定义的顺序来匹配,见下例:
Java代码
1.package x.y;
2.
3.public class Foo {
4.
5. //构造器的参数类型分别是Bar和Baz
6.
7. public Foo(Bar bar, Baz baz) {
8.
9. }
10.
11.}
packagex.y;
publicclassFoo{
//构造器的参数类型分别是Bar和Baz
publicFoo(Barbar,Bazbaz){
}
}
看下其配置:
Xml代码
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
再看下有简单类型的情况:
Java代码
1.package examples;
2.
3.public class ExampleBean {
4.
5. //简单类型虽然明确,但在配置时必须指明type才能匹配
6.
7. private int years;
8.
9. // 同上
10.
11. private String ultimateAnswer;
12.
13. public ExampleBean(int years, String ultimateAnswer) {
14.
15. this.years = years;
16.
17. this.ultimateAnswer = ultimateAnswer;
18.
19. }
20.
21.}
packageexamples;
publicclassExampleBean{
//简单类型虽然明确,但在配置时必须指明type才能匹配
privateintyears;
//同上
privateStringultimateAnswer;
publicExampleBean(intyears,StringultimateAnswer){
this.years=years;
this.ultimateAnswer=ultimateAnswer;
}
}
看下其配置情况:
Xml代码
1.
2.
3.
4.
5.
---指明类型-à
6.
7.
8.
9.
10.
11.
12.
13.
---指明类型-à
也可以用索引的方式达上与上面同样的效果:
Xml代码
1.
2.
3.
4.
5.
---索引从0开始-à
6.
7.
8.
9.
10.
11.
12.
13.
---索引从0开始-à
Setter注入:
通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现基于setter的DI。
如:
Java代码
1.public class SimpleMovieLister {
2.
3. //依赖MovieFinder
4.
5. private MovieFinder movieFinder;
6.
7.//用setter方法注入
8.
9. public void setMovieFinder(MovieFinder movieFinder) {
10.
11. this.movieFinder = movieFinder;
12.
13.}
14.
15.}
publicclassSimpleMovieLister{
//依赖MovieFinder
privateMovieFindermovieFinder;
//用setter方法注入
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
}
构造器注入与setter注入的选择?
根据具体情况使用,一般而言,构造器注入不宜依赖参数过多的情况,否则构造器显得比较臃肿,参数类型或名字以及顺序也容易写错。
Setter注入当依赖对象过多的时候可以考虑,缺点就是代码也可能臃肿。
处理Bean依赖关系的步骤:
a) 根据bean配置文件创建并初始化BeanFactory实例,一般使用ApplicationContext实现。
b) Bean被创建的时候,依赖的属性、构造器参数或静态工厂方法参数都要提供给此bean。
c) 依赖的属性或构造器参数可以是一个值也可以是个引用。
d) 指定的属性或构造器参数值必须能转换成特定的格式或构造器参数所需的类型。
Spring容器在创建的时候会对每个配置的bean进行验证,检查bean指定的属性引用是否有效。
在bean实际被创建之前,依赖的属性是不会被设置的,对于单例或被设置提前实例化的bean将与容器同时创建。
其它情况的bean会被延迟到使用时才创建。
默认情况下,ApplicationContext实现中的bean采用提前实例化的singleton模式,这样做的好处是可以提前进行配置检查。
被依赖的bean必须在依赖bean创建之前配置好。
一些例子:
Setter注入的配置:
Java代码
1.public class ExampleBean {
2.
3. //依赖的属性
4.
5. private AnotherBean beanOne;
6.
7. private YetAnotherBean beanTwo;
8.
9. private int i;
10.
11. //用setter方法注入
12.
13. public void setBeanOne(AnotherBean beanOne) {
14.
15. this.beanOne = beanOne;
16.
17. }
18.
19. public void setBeanTwo(YetAnotherBean beanTwo) {
20.
21. this.beanTwo = beanTwo;
22.
23. }
24.
25. public void setIntegerProperty(int i) {
26.
27. this.i = i;
28.
29. }
30.
31.}
publicclassExampleBean{
//依赖的属性
privateAnotherBeanbeanOne;
privateYetAnotherBeanbeanTwo;
privateinti;
//用setter方法注入
publicvoidsetBeanOne(AnotherBeanbeanOne){
this.beanOne=beanOne;
}
publicvoidsetBeanTwo(YetAnotherBeanbeanTwo){
this.beanTwo=beanTwo;
}
publicvoidsetIntegerProperty(inti){
this.i=i;
}
}
Xml代码
1.public class ExampleBean {
2.
3. //依赖的属性
4.
5. private AnotherBean beanOne;
6.
7. private YetAnotherBean beanTwo;
8.
9. private int i;
10.
11. //用setter方法注入
12.
13. public void setBeanOne(AnotherBean beanOne) {
14.
15. this.beanOne = beanOne;
16.
17. }
18.
19. public void setBeanTwo(YetAnotherBean beanTwo) {
20.
21. this.beanTwo = beanTwo;
22.
23. }
24.
25. public void setIntegerProperty(int i) {
26.
27. this.i = i;
28.
29. }
30.
31.}
publicclassExampleBean{
//依赖的属性
privateAnotherBeanbeanOne;
privateYetAnotherBeanbeanTwo;
privateinti;
//用setter方法注入
publicvoidsetBeanOne(AnotherBeanbeanOne){
this.beanOne=beanOne;
}
publicvoidsetBeanTwo(YetAnotherBeanbeanTwo){
this.beanTwo=beanTwo;
}
publicvoidsetIntegerProperty(inti){
this.i=i;
}
}
构造器注入的配置:
Java代码
1.public class ExampleBean {
2.
3. //依赖的对象
4.
5. private AnotherBean beanOne;
6.
7. private YetAnotherBean beanTwo;
8.
9. private int i;
10.
11. //注入到构造器中
12.
13. public ExampleBean(
14.
15. AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
16.
17. this.beanOne = anotherBean;
18.
19. this.beanTwo = yetAnotherBean;
20.
21. this.i = i;
22.
23. }
24.
25.}
publicclassExampleBean{
//依赖的对象
privateAnotherBea
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Spring 思想 注入 依赖 学习 笔记
![提示](https://static.bdocx.com/images/bang_tan.gif)