我们可以通过Spring当中提供的注解@Component以及它的三个衍生注解(@Controller、@Service、@Repository)来声明IOC容器中的bean对象,为应用程序注入运行时所需要依赖的bean对象,也就是依赖注入DI。

关于IOC容器中Bean的其他使用细节,主要包括以下三方面:

  1. 获取IOC中的Bean
  2. 通过注解声明时的一些细节
  3. 第三Bean的创建

1. 如何从IOC容器中手动的获取到bean对象

这里就不谈DI的方式了哈

SpringBoot项目在启动的时候会自动的创建IOC容器(也称为Spring容器),并且在启动的过程当中会自动的将bean对象都创建好,存放在IOC容器当中。应用程序在运行时需要依赖什么bean对象,就直接进行依赖注入就可以了。

而在Spring容器中提供了一些方法,可以主动从IOC容器中获取到bean对象,下面介绍3种常用方式:

  1. 根据name获取bean 容器中默认为当前类的首字母小写

    Object getBean(String name)
    
  2. 根据类型获取bean

    <T> T getBean(Class<T> requiredType)
    
  3. 根据name获取bean(带类型转换)

    <T> T getBean(String name, Class<T> requiredType)
    

如果知道Spring注入的方式其实也就对应着在DI时,即依赖注入时的两种方式及按照名称,按照类型,还有当有多个实现类时,如果区分。

下面就通过代码来获取以及查看容器中的bean

定义一个父接口:

public interface FatherInterface {void hello();
}

定义一个实现类,实现父接口;注意加上@Component注解,表示这个类让Spring管理

@Component
public class SonComponent implements FatherInterface{@Overridepublic void hello() {System.out.println("There is son");}
}

然后在测试类中注入容器对象,从容器中通过上面的三个方法获取bean

@SpringBootTest(classes = SkyApplication.class) // 这里因为我当前的项目是多模块所以需要指定一下
public class MyTestDemo {// 这个对象就是Springioc容器对象@Autowiredprivate ApplicationContext application;@Testpublic void testGetBean(){// 方式一 根据name获取beanFatherInterface bean1 = (FatherInterface)application.getBean("sonComponent");System.out.println(bean1);// 方式二 根据类型获取beanFatherInterface bean2 = application.getBean(FatherInterface.class);System.out.println(bean2);// 方式三 根据name获取bean(带类型转换)FatherInterface bean3 = application.getBean("sonComponent",FatherInterface.class);System.out.println(bean3);}
}

控制台可见三种方式都可以获得到当前对象,并且当前地址相同

第三种存在的意义在于当使用第二种方式来获取的时候如果接口有两个实现类时,通过名字来区分。

比如现在:一个接口,两个实现类,如果再通过第二种方式获取就会出现异常,因为当按照类型查找时有两个Spring并不知道是哪个

报错主要信息如下:

available: expected single matching bean but found 2:

此时就需要通过名字来指定。

在Spring中我们也可以通过图形化界面来查看容器中的内容,其中高亮的是Spring所依赖的文件,其他的是第三方或我们自己编写bean。

在Spring中也提供了另一种方式通过在子类中使用**@Primary**,来指定当有通过类型获取的时候当有多个实现类时使用哪一个。

2. bean的作用域配置

通过上面我们可以看到不管通过哪一种方式得到的地址都是相同的,也就是单例。可见Spring默认创建的对象都是单例模式。

单例: 指的是在运行环境中一个类:只存在一个对象
spring 默认就是单例

@Scope 表示 作用范围
singleton 单例: 程序运行时只会创建一个对象
1) spring 启动时 就初始化
2) 想要使用时才初始化 应该加 @Lazy
prototype 多例: 每获取一次对象,都创建一个新的
使用时才初始化

写上的话提示:冗余默认参数值分配 即默认。

在Spring中支持五种作用域,后三种在web环境才生效:主要记忆前两种,一个单例一个多例。

作用域 说明
singleton 容器内同名称的bean只有一个实例(单例)(默认)
prototype 每次使用该bean时会创建新的实例(非单例)
request 每个请求范围内会创建新的实例(web环境中,了解)
session 每个会话范围内会创建新的实例(web环境中,了解)
application 每个应用范围内会创建新的实例(web环境中,了解)

把当前类的的@Scope注解的value修改为prototype

@Component
@Slf4j
@Scope(value ="prototype")
public class SonComponent implements FatherInterface{....
}

此时再运行查看控制台当前就是多例,而对于创建时机,单例默认是Spring容器初始化时,可以通过@Lazy来指定

3. 管理第三方的bean对象

之前我们所配置的bean,像controller、service,dao三层体系下编写的类,这些类都是我们在项目当中自己定义的类(自定义类)。当我们要声明这些bean,也非常简单,我们只需要在类上加上@Component以及它的这三个衍生注解(@Controller、@Service、@Repository),就可以来声明这个bean对象了。
但是在我们项目开发当中,还有一种情况就是这个类它不是我们自己编写的,而是我们引入的第三方依赖当中提供的。

比如我们要使用dom4j 对xml文件进行解析的时候。因为dom4j就是第三方组织提供的。 dom4j中的SAXReader类就是第三方编写的。

按照我们之前的做法,需要在SAXReader类上添加一个注解@Component(将当前类交给IOC容器管理)

但是第三方提供的类是只读的。无法在第三方类上添加@Component注解或衍生注解。

那么我们应该怎样使用并定义第三方的bean呢?

  • 如果要管理的bean对象来自于第三方(不是自定义的),是无法用@Component 及衍生注解声明bean的,就需要用到**@Bean**注解。

解决方案1:在启动类上添加@Bean标识的方法

@SpringBootApplication
public class SpringbootWebConfig2Application {public static void main(String[] args) {SpringApplication.run(SpringbootWebConfig2Application.class, args);}//声明第三方bean@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器beanpublic SAXReader saxReader(){return new SAXReader();}
}

您可能会问,同样是new ,我使用的时候不使用注入使用new不好吗? 不好,如果当多次使用的时候每次都是新的对象,这样不便于管理。我们使用IOC的规则就是将对象,统一交给Spring容器(IOC容器)统一管理。

此时容器中就有了SAXReader对象,但在容器中的对象的名字是方法名

说明:以上在启动类中声明第三方Bean的作法,不建议使用(项目中要保证启动类的纯粹性)

解决方案2:在配置类中定义@Bean标识的方法

既然要保证启动类的纯粹性那么我们就创建一个配置类,专为第三方类服务。

@Configuration //配置类  (在配置类当中对第三方bean进行集中的配置管理)
public class CommonConfig {//声明第三方bean@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean//通过@Bean注解的name/value属性指定bean名称, 如果未指定, 默认是方法名public SAXReader reader(DeptService deptService){System.out.println(deptService);return new SAXReader();}
}

如下:

在方法上加上一个@Bean注解,Spring 容器在启动的时候,它会自动的调用这个方法,并将方法的返回值声明为Spring容器当中的Bean对象。

注意事项 :

  • 通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名。

  • 如果第三方bean需要依赖其它bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配。

关于Bean大家只需要保持一个原则:

  • 如果是在项目当中我们自己定义的类,想将这些类交给IOC容器管理,我们直接使用@Component以及它的衍生注解来声明就可以。
  • 如果这个类它不是我们自己定义的,而是引入的第三方依赖当中提供的类,而且我们还想将这个类交给IOC容器管理。此时我们就需要在配置类中定义一个方法,在方法上加上一个@Bean注解,通过这种方式来声明第三方的bean对象。

既然说到了这里那么关于声明Bean时的几个条件注解是少不了的,也就是通过注解,来告诉Spring我们在什么条件下才去创建这个Bean。即按照条件装配。在另一个笔记中:


@Conditional四个较常用的派生注解总结

SpringBoot中对Bean的处理方法以及第三方Bean处理的方式相关推荐

  1. SpringBoot 中 @RequestBody的正确使用方法

    SpringBoot 中 @RequestBody的正确使用方法 最近在接收一个要离职同事的工作,接手的项目是用SpringBoot搭建的,其中看到了这样的写法: [java] view plain  ...

  2. SpringBoot中通过重写WebMvcConfigurer的方法配置静态资源映射实现图片上传后返回网络Url

    场景 前端调用上传照片的功能,将某照片上传到服务器上某磁盘路径下,然后将通过静态资源映射,将在服务器上 访问的地址存储到数据库中,这样在需要获取这种照片的时候就能通过服务器上的url来获取和显示这张照 ...

  3. SpringBoot中使用thymeleaf的trim方法进行判断字符串是否相等

    场景 在thymeleaf中进行string字符串的数字进行判断是否相等进而显示相应的中文内容. 但是后台传递的数据是'1 ' 即1的后面有一个空格. 所以在thymeleaf中进行判读时需要使用tr ...

  4. SpringBoot中service注入失败(A component required a bean of type ‘XXService‘ that could not found)...

    先写了JUnit,发现启动不了,注释掉有问题的service也不可以.可能是因为spring开始时会加载所有service吧. 按照网友们的说法,一般需要检查: 1.入口类有没有写MapperScan ...

  5. SpringBoot学习笔记(9)----SpringBoot中使用关系型数据库以及事务处理

    在实际的运用开发中,跟数据库之间的交互是必不可少的,SpringBoot也提供了两种跟数据库交互的方式. 1. 使用JdbcTemplate 在SpringBoot中提供了JdbcTemplate模板 ...

  6. yaml语法格式,springboot中yaml的使用

    yaml语法格式,springboot中yaml的使用 yaml 1.yaml语法格式 2.数据类型表示 springboot中yaml的使用 1. @ConfigurationProperties注 ...

  7. php中函数的使用方法,php中header()函数的使用方法

    本文主要和大家分享php中header()函数的使用方法,主要以代码的方式和大家讲解,希望能帮助到大家.跳转页面 header('Location:'.$url); //Location和" ...

  8. Collections中min和max工具方法详解

    以下是java.util.Collections.min()方法和java.util.Collections.min()的声明 public static <T extends Object & ...

  9. SpringBoot中@PropertySource和@ImportResource以及@Bean

    @PropertySource 加载指定的配置文件 只能加载*.properties文件,不能加载yaml文件 新建一个user.properties user.nickname=张三 user.ag ...

最新文章

  1. MVCAction接收数据方式
  2. 虚拟form 下载文件
  3. iphone 使用委托(delegate)在不同的窗口之间传递数据
  4. RawCode-本身就是实验性的8位类型
  5. 提升你的开发效率,10 个 NPM 使用技巧
  6. sql server 按照日期自动生成单据编号的函数
  7. ROS笔记(24) Amcl
  8. echarts曲线太多卡顿怎么优化_光刻胶旋涂曲线如何获得?
  9. 编写 matlab_MATLAB的SFunction编写指导
  10. BZOJ 2820: YY的GCD
  11. 更改主机文件引发思考 防火墙URL过滤无奈(转)
  12. Pytorch优化器全总结(二)Adadelta、RMSprop、Adam、Adamax、AdamW、NAdam、SparseAdam
  13. 手把手教你修改butterfly主题的样式
  14. Kinect_人脸识别
  15. Java实现 蓝桥杯 算法提高 天天向上(DP)
  16. Vue整合Markdown组件+SpringBoot文件上传+代码差异对比
  17. 来soul,遇见你的奇妙缘分
  18. 老年手机英文改中文_老年人使用智能手机(九)不会英语不用怕,装一款软件就能出国啦...
  19. 网站如何备案 怎么备案 网站备案流程有哪些?
  20. codeforces1064E Dwarves, Hats and Extrasensory Abilities

热门文章

  1. (二)最常用的量子计算模型——量子线路
  2. OceanFax传真服务器连续第二年荣获“中国优秀软件产品奖”
  3. 比原链BTM GPU挖矿软件(NebuTech BTMiner3.0)-大幅提升算力
  4. 关于wow网游中软件管理的设想
  5. 将个人java web网站发布至公网#内网穿透#花生壳#手把手教程
  6. 浅谈Java中的BigInteger类
  7. 设计模式:Decorator(装饰者模式)
  8. Pycharm 搭建pyspark开发环境
  9. 维纳滤波、维纳霍夫方程及矩阵形式
  10. jQuery简单体验及jQuery中文手册下载