前言
这段时间在学习spring,依赖注入di和面向切面编程aop是spring框架最核心的部分。这次主要是总结依赖注入的bean的装配方式。
什么是依赖注入呢?也可以称为控制反转,简单的来说,一般完成稍微复杂的业务逻辑,可能需要多个类,会出现有些类要引用其他类的实例,也可以称为依赖其他类。传统的方法就是直接引用那个类对象作为自己的一个属性,但如果我们每次创建这个类的对象时,都会创建依赖的类的对象,还有如果那个类将来可能不用了,还需要到这个类去删除这个对象,那破坏了代码的复用性和导致高度耦合!
依赖注入的出现可以很好地解决这个问题,依赖注入就是由系统负责协调类的依赖对象的创建,我们无需自己去显示的创建依赖对象,而是由系统给我们注入这个对象,系统控制了这个对象的创建,也称为控制反转。
spring给我们注入对象有三种方式:
- 隐式的bean扫描发现机制和自动装配
- 在java中进行显示配置
- 在xml中进行显示配置
第一种:
spring从两个角度实现自动化装配:组件扫描和自动装配。
当对一个类标注@component注解时,表明该类会作为组件类,spring将为这个类创建bean。当在应用文中引用这个bean,spring会自动扫描事先指定的包查找这个 bean。但spring默认是不启用组件扫描的,可以在xml中配置加上<context:component-scan base-package="xx"/>
。还有一种方法:在新建一个配置类,类中可以什么不用写,在配置类上加上@componentscan注解,spring会自动扫描改配置类所在的包,一般应该倾向xml配置。下面是一个bbs论坛系统用户发帖的功能小例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package bbs.dao; @component public interface postdao { /* *用户发帖 ,post表添加帖子信息 */ public int addpost(@param("title") string title,@param("content") string content,@param("userid") int userid); } package bbs.dao; @component public interface userdao { /* * 用户发帖后,user表将用户发帖数加一 */ public int addpost( int userid); } |
再在bbs.service包中创建一个postservice接口及其实现类,依赖postdao和userdao。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package bbs.service; public interface postservice { /* 用户发帖后,先添加帖子信息再更新用户发帖数量 */ public void addpost(string title,string content, int userid); } package bbs.service; @component public class postserviceimpl implements postservice { private postdao postdao; private userdao userdao; // @autowired // public void setpostdao(postdao postdao) // { // this.postdao=postdao; // } // // @autowired // public void setuserdao(userdao userdao) // { // this.userdao=userdao; // } @autowired public postserviceimpl(postdao postdao,userdao userdao) { this .userdao=userdao; this .postdao=postdao; } public void addpost(string title, string content, int userid) { int i=postdao.addpost(title, content, userid); int j=userdao.addpost(userid); if (i== 1 &j== 1 ) system.out.println( "发帖成功" ); else system.out.println( "发帖失败" ); } } |
@component在接口实现上注解就可以,但发现在userdao、postdao接口也加上了,其实可以去掉,因为我采用mybatis在xml中配置数据库的操作,动态实现dao接口。等下会提到。上面代码出现的@autowired注解实现bean自动装配,会在spring应用上下文中的组件类寻找需求的bean。一般有两种装配方式:构造器和setter方法(其他方法名也行,只要能够使注入的bean成为这个类的属性就行)
也可能出现spring没有查找到匹配的bean会抛出异常,在@autowired加上required=false
,如果没有匹配的bean时,spring会使这个bean处于未装配的状态,没有装配成功。还有可能会出现相同名字的bean有很多个,会产生歧义,一般在组件类上添加注解@qualifier()
括号写这个bean的id,在注入时也加上@qualifier()
,写上bean的id。像下面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@component @qualifier ( "postdao" ) public interface postdao{ . . . . } @component @qualifier ( "userdao" ) public interface userdao{ . . . . } @autowired @qualifier ( "usedao" ) public void setuserdao(userdao userdao) {. . . } @autowired @qualifier ( "postdao" ) public void setuserdao(postdao postdao) {. . . } |
由于java不允许在同一个条目上重复出现相同类型的多个注解,所有注入采用set方式。但是其实可以创建自定义的限定符注解。这里就不介绍啦。
第二种:
通过java代码装配bean
一般通过组件扫描和自动装配方式就比较方便了,但如果由于需求我们要使用第三方的库的类,在这种情况没有办法到第三方库中去给类加注解,就不能使用第一种方法了。这时得采用显示装配,可以采用java代码或xml显示装配bean。使用java代码,先新建一个配置类javaconfig,里面都是配置所需的bean,不应该有业务逻辑代码,所以单独建一个类。
1
2
3
4
5
6
7
8
9
10
|
@configuration @contextconfiguration (locations = { "classpath:spring/spring-dao.xml" , "classpath:scan.xml" }) public class bbsconfig{ private postdao postdao; private userdao userdao; @bean (name= "postservice" ) public postservice getpost() { return new postserviceimpl(postdao,userdao); } |
在对postservice的bean注入时,同时又依赖了两个bean,postdao和userdao。直接引用beanid就可以,spring会自动地从容器中获取这些bean,只要他们的配置是正确的就行。这个例子中userdao、postdao是mybatis配置自动扫描将dao接口生成代理注入到spring的,其实也算是xml装配bean。可参考这篇文章,写的挺清楚的。
这里如果再声明一个bean,返回的仍是postserviceimpl对象,和之前的那个bean完全一样,是同一个实例。一般spring@bean如果是同一个beanid,默认返回的是一个单例bean,注入的是同一个实例。如果修改其中一个会都改变的。
不过在这里要注意进行测试时,由于spring的单元测试和springioc容器是完全独立的,postdao和userdao注入检测时是使用locations加载xml文件,而postservice使用classes加载config类的,但是两个不能同时混用在@contextconfiguration中。所以非要都测试的话,就分开测试吧。
第三种:
在xml中装配bean
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?xml version= "1.0" encoding= "utf-8" ?> <beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans.xsd http: //www.springframework.org/schema/context"> < import resource= "spring/spring-dao.xml" /> <bean id= "postservice" class = "com.bbs.service.impl.postserviceimpl" > <constructor-arg ref= "postdao" /> <constructor-arg ref= "userdao" /> </bean> </beans> |
配置postservice的bean时需要引入两个bean,postdao和userdao,放到constructor-arg的标签中,ref指的是依赖的bean的id。如果是在javaconfig中配置的,就写@bean的内容。如果是@component就写@qualifier的内容。这里是引入的是动态实现的dao接口的bean,是在spring-dao.xml中配置的,引入这个配置文件就可以自动获得beanid。
混合使用三种装配:
1.在类上可以使用@ import(bbsconfig.class)
组合其他java注解
2.在类上使用@ imortresource("classpath:spring-dao.xml")
组合其他xml注解
3.在类上可以使用@contenxtconfiguration
包含class或者xml
4.在xml中可以用<import resource="spring-dao.xml">
引入xml注解,也可以使用<bean class="com.bbs.dao.userdao">
引入java注解
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。
原文链接:https://www.cnblogs.com/maxshare/p/10467761.html