【如果转载不要忘了注明转载地址哈】

这段时间在学习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论坛系统用户发帖的功能小例子:

 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。

 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。像下面:

 @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,不应该有业务逻辑代码,所以单独建一个类。

@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。可参考这篇文章,写的挺清楚的。https://bijian1013.iteye.com/blog/2318860

这里如果再声明一个bean,返回的仍是postserviceImpl对象,和之前的那个bean完全一样,是同一个实例。一般spring@bean如果是同一个beanID,默认返回的是一个单例bean,注入的是同一个实例。如果修改其中一个会都改变的。

不过在这里要注意进行测试时,由于spring的单元测试和springIoc容器是完全独立的,postdao和userdao注入检测时是使用locations加载xml文件,而postservice使用classes加载config类的,但是两个不能同时混用在@ContextConfiguration中。所以非要都测试的话,就分开测试吧。

第三种:

在XML中装配bean

<?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注解

spring 装配bean的三种方式的更多相关文章

  1. spring装配bean的三种方式及其混合装配

    在spring容器中装配bean有三种基本方式和混合装配方式: 隐式的bean自动发现机制和自动装配 在java中进行显式配置 在xml中配置 混合装配(在多个java文件中配置.在JavaConfi ...

  2. Spring装配Bean的三种方式+导入和混合配置

    目录 Spring IoC与bean 基于XML的显式装配 xml配置的基本结构 bean实例的三种创建方式 依赖注入的两种方式 构造器注入方式 setter方法注入方式 利用命名空间简化xml 基于 ...

  3. spring创建bean的三种方式

    spring创建bean的三种方式: 1通过构造方法创建bean(最常用) 1.1 spring默认会通过无参构造方法来创建bean,如果xml文件是这样配置,则实体类中必须要有无参构造方法,无参构造 ...

  4. Spring容器装配Bean的三种方式

    欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝 ...

  5. Spring实战(三)Spring中装配Bean的三种方式---XML、JavaConfig、AutoWire

    创建应用对象之间协作关系的行为称为装配(wiring),这也是依赖注入的本质. Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系,而开发者需要告诉Spring需要创建哪些 ...

  6. 装配Bean的三种方式

    一.装配Bean就是在xml写一个Bean标签:装配完Bean,还需要读取xml配置文件创建Spring容器来创建对象: 1.new 实现类方式 正常的三种创建Bean容器的方法都可以根据装配的Bea ...

  7. Spring 实例化bean的三种方式

    第一种方法:直接配置Bean <bena id="所需要实例化的一个实例名称" class="包名.类名"/> 例如: 配置文件中的bean.XML ...

  8. Spring实例化Bean的三种方式及Bean的类型

    1.使用类构造器实例化  [默认的类构造器] <bean id=“orderService" class="cn.itcast.OrderServiceBean"/ ...

  9. spring实例化bean的三种方式

    公共使用的实体

随机推荐

  1. 程序员 & 设计师都能用上的 75 份速查手册

    分享75份开发人员和设计师会用到的速查手册,由 vikas 收集整理,包括:jQuery.HTML.HTML5.CSS.CSS3.JavaScript.Photoshop .git.Linux.Jav ...

  2. [vmware]另类解决vmware关闭win10死机或蓝屏问题

    升级win10后在使用虚拟机发生一个问题,本人的win10版本为win10 9879, 在使用vmware时,当关机会整个系统死机,在网上搜索后发现这是由于win10内核升级导致vmware不兼容,最 ...

  3. 运用jQuery实现动态点赞

    写一个动态点赞的小案例吧! 虽然有点low,但是初学者可以看看! .Css文件 .content{ border: 1px solid black; font-size: 20px; height: ...

  4. node.js 基础篇

    日志输出方式 node test.js 2>error.log 1>info.log 如果需要日志文件追加 node test.js 2>>error.log 1>> ...

  5. 树形dp(B - Computer HDU - 2196 )

    题目链接:https://cn.vjudge.net/contest/277955#problem/B 题目大意:首先输入n代表有n个电脑,然后再输入n-1行,每一行输入两个数,t1,t2.代表第(i ...

  6. [转]QVector与QByteArray——Qt的写时复制(copy on write)技术

    我们在之前的博文QVector的内存分配策略与再谈QVector与std::vector——使用装饰者让std::vector支持连续赋值中简单聊了聊QVector内存分配和赋值方面的一点东西,今天接 ...

  7. LCD时序中设计到的VSPW/VBPD/VFPD/HSPW/HBPD/HFPD总结【转】

    转自:https://blog.csdn.net/u011603302/article/details/50732406 下面是我在网上摘录的一些关于LCD信号所需时钟的一些介绍, 描述方式一: 来自 ...

  8. Linux禁止ping的俩种方法【转】

    Linux禁止ping以及开启ping的方法   Linux默认是允许Ping响应的,系统是否允许Ping由2个因素决定的:A.内核参数,B.防火墙,需要2个因素同时允许才能允许Ping,2个因素有任 ...

  9. Django-自动HTML转义

    一.自动HTML转义 从模板生成HTML时,总会有变量包含影响最终HTML的字符风险,例如,考虑这个模板的片段: Hello, {{ name }} 起初,这是一种显示用户名的无害方式,但考虑用户输入 ...

  10. centos7.2系统没有eth0网卡

    最近一直在学centos7.5系统,偶然看到虚拟机里有7.2系统所以想练习一下(其实7.2和7.5差不多),但是打开虚拟机之后,发现没有eth0网卡 那没有eth0网卡就无法远程连接ssh,既然遇到了 ...