前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记下来,spring 装配bean的三种方式!

记下来,spring 装配bean的三种方式!

作者头像
JAVA葵花宝典
发布2019-05-24 20:37:40
5720
发布2019-05-24 20:37:40
举报
文章被收录于专栏:JAVA葵花宝典JAVA葵花宝典

作者:max-先生 来源:https://www.cnblogs.com/maxshare/p/10467761.html ps:拿笔记一下,面试可能会考。依赖注入DI和面向切面编程AOP是Spring框架最核心的部分。这次主要是总结依赖注入的bean的装配方式。

前言

什么是依赖注入呢?也可以称为控制反转,简单的来说,一般完成稍微复杂的业务逻辑,可能需要多个类,会出现有些类要引用其他类的实例,也可以称为依赖其他类。传统的方法就是直接引用那个类对象作为自己的一个属性,但如果我们每次创建这个类的对象时,都会创建依赖的类的对象,还有如果那个类将来可能不用了,还需要到这个类去删除这个对象,那破坏了代码的复用性和导致高度耦合!

依赖注入的出现可以很好地解决这个问题,依赖注入就是由系统负责协调类的依赖对象的创建,我们无需自己去显示的创建依赖对象,而是由系统给我们注入这个对象,系统控制了这个对象的创建,也称为控制反转。

Spring给我们注入对象有三种方式

  • 隐式的bean扫描发现机制和自动装配
  • 在java中进行显示配置
  • 在XML中进行显示配置

第一种:

spring从两个角度实现自动化装配:组件扫描和自动装配。

当对一个类标注@Component注解时,表明该类会作为组件类,spring将为这个类创建bean。当在应用文中引用这个bean,spring会自动扫描事先指定的包查找这个 bean。但spring默认是不启用组件扫描的,可以在XML中配置加上。还有一种方法:在新建一个配置类,类中可以什么不用写,在配置类上加上@ComponentScan注解,spring会自动扫描改配置类所在的包,一般应该倾向xml配置。下面是一个bbs论坛系统用户发帖的功能小例子:

代码语言:javascript
复制
 1 package bbs.dao; 2 @Component 3 public interface Postdao { 4     /* 5      *用户发帖 ,post表添加帖子信息 6      */ 7     public int addpost(@Param("title") String title,@Param("content") String content,@Param("userid") int userid); 8 } 9 10 package bbs.dao;11 @Component12 public interface Userdao {13     /*14      * 用户发帖后,user表将用户发帖数加一15      */16     public int addpost(int userid);17 }

再在bbs.service包中创建一个postservice接口及其实现类,依赖Postdao和Userdao。

代码语言:javascript
复制
 1 package bbs.service; 2 public interface PostService { 3     /* 4     用户发帖后,先添加帖子信息再更新用户发帖数量 5     */ 6     public void addpost(String title,String content,int userid); 7 }
代码语言:javascript
复制
 9 package bbs.service;10 @Component11 public class PostserviceImpl implements PostService {12 13     private Postdao postdao;14     private Userdao userdao;15 16 //    @Autowired17 //    public void setPostdao(Postdao postdao)18 //    {19 //        this.postdao=postdao;20 //    }21 //22 //    @Autowired23 //    public void setUserdao(Userdao userdao)24 //    {25 //        this.userdao=userdao;26 //    }27 28     @Autowired29     public PostserviceImpl(Postdao postdao,Userdao userdao)30     {31         this.userdao=userdao;32         this.postdao=postdao;33     }34 35     public void addpost(String title, String content, int userid) {36         int i=postdao.addpost(title, content, userid);37         int j=userdao.addpost(userid);38         if(i==1&j==1)39             System.out.println("发帖成功");40         else41             System.out.println("发帖失败");42     }43 }

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

代码语言:javascript
复制
 1 @Component 2 @Qualifier("postdao") 3 public interface Postdao{ 4 . . . .      5 } 6   7 @Component 8 @Qualifier("userdao") 9 public interface Userdao{10 . . . . 11 }12 13 @Autowired14 @Qualifier("usedao")15 public void setUserdao(Userdao userdao)16 {. . . 17 }18  19 @Autowired20 @Qualifier("postdao")21 public void setUserdao(Postdao postdao)22 {. . . 23 }

由于java不允许在同一个条目上重复出现相同类型的多个注解,所有注入采用set方式。但是其实可以创建自定义的限定符注解。这里就不介绍啦。

第二种:

通过java代码装配bean

一般通过组件扫描和自动装配方式就比较方便了,但如果由于需求我们要使用第三方的库的类,在这种情况没有办法到第三方库中去给类加注解,就不能使用第一种方法了。这时得采用显示装配,可以采用java代码或xml显示装配bean。使用java代码,先新建一个配置类JavaConfig,里面都是配置所需的bean,不应该有业务逻辑代码,所以单独建一个类。

代码语言:javascript
复制
@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

代码语言:javascript
复制
<?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中可以用引入xml注解,也可以使用引入java注解

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA葵花宝典 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 第一种:
  • 第二种:
    • 通过java代码装配bean
    • 第三种:
      • 在XML中装配bean
      • 混合使用三种装配:
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档