Spring框架(基于注解装配Bean)

目录,更新ing,学习Java的点滴记录

  目录放在这里太长了,附目录链接大家可以自由选择查看--------Java学习目录

Spring知识

  一丶SpringIOC初步认识↓↓↓
第一篇---->初识Spring
  二丶SpringIOC深入↓↓↓
第二篇---->深入SpringIoC容器(一)
第三篇---->深入SpringIoC容器(二)
  三丶装配SpringBean↓↓↓
第四篇---->依赖注入的方式
第五篇---->基于xml装配Bean
第六篇---->基于注解装配Bean
第七篇---->Spring Bean之间的关系
第八篇---->SpringBean的作用域
第九篇---->Spring 加载属性(properties)文件
第十篇---->Spring表达式(SpEL)
第十一篇---->Spring在xml中配置组件扫描
  四丶面向切面编程↓↓↓
第十二篇—>认识SpringAOP及底层原理
第十三篇—>使用@AspectJ注解开发AOP
第十四篇—>使用xml配置开发AOP
  五丶Spring中数据库编程↓↓↓
第十五篇—>数据库编程JdbcTemplate
  六丶Spring事务管理↓↓↓
第十六篇—>Spring事务管理初识
第十七篇—>编程式事务和声明式事务
第十八篇—>事务ACID特性
第十九篇—>事务传播行为
第二十篇—>事务隔离级别

5 通过注解装配Bean

5.1 注解装配介绍

  • 上面说完了xml装配的各种方式,终于到了注解方式了,这也是重头戏,更多时候已经不再推荐使用xml方式去装配Bean,更多时候会考虑使用注解(annotation)的方式去装配Bean.
  • 使用注解的方式可以极大减少xml的配置,采用了自动装配后,开发人员所需要做的工作就少了很多,有利于程序的开发,这就是"约定优于配置"的开发原则.
  • 在Spring中,提供了两种方式来让SpringIOC容器发现Bean.
      1) 组件扫描:通过定义资源的方式,让SpringIOC容器扫描对应的包,从而把Bean装配进来
      2) 自动装配:通过注解定义,使得一些依赖关系可以通过注解完成
  • 通过扫描和自动装配,大部分的工程都可以用 Java 配置完成,而不是 XML,这样可以有效减少配置和引入大量 XML, 它解决了在 Spring 3 之前的版本需要大量的 XML 配置的问题。由于目前注解已经成为 Spring 开发的主流,以注解为主, 以 XML 为辅.

5.2 使用@Component装配

  • 定义一个JavaBean,User类
      在这里插入图片描述
  • 说明
      1) 注解@Component代表SpringIOC会把这个类扫描生成Bean实例,而其中的value属性代表这个类在Spring中的id,这就相当于xml方式定义的Bean的id,也可以简写成@Component(“user”),甚至直接写成@Component,对于不写value属性的,SpringIOC就默认为类名首字母小写后的形式作为id.,生成的对象会配置到容器中.
      2) 注解value代表值的注入,如@Value(“root”)表示容器生成对User对象的name属性为root
  • 现在配置好了JavaBean类,就需要配置扫描了,SpringIOC会根据我们设置的扫描路径去查找由它默认帮我们初始化的对象
      在这里插入图片描述
  • 说明:
      1) 包名和定义的User类的包名是一致的
      2) @ComponentScan表示进行扫描,而扫描的默认路径就是当前包的路径,由于User类也在该包中,所以也会被扫描到
  • 测试代码获取Bean实例–通过SpringIOC容器的另一个实现类(AnnotationConfigApplicationContext),这里需要额外添加一个jar包(Spring框架学习第壹篇中有提供jar包下载方式和资料—Spring(一))
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 可以看到使用AnnotationConfigApplicationContext类去初始化SpringIOC容器,但是要传入含有@ComponentScan注解的类,这样SpringIOC就会根据注解的配置去解析资源,生成容器.
  • 弊端:
     1) @ComponentScan注解默认情况下只会扫描所在包及其子包下的Java类,但是没有做到可以扫描指定的类,默认情况下,无法更加精确.
     2) 上面示例中仅仅注入了一些很简单的值,没有注入对象.

5.3 使用@ComponentScan精确扫描

  • @ComponentScan存在两个配置项:第一个是basePackages,它是由base和package两个单词组成,而package还使用了复数,意味着它可以配置一个java包的数组,Spring会根据它的配置扫描对应的包和子包,并将配置好的Bean装配到容器中.第二个是basePackageClasses,它是由base,package和class三个单词组成的,采用复数,意味着它可以配置多个类,Spring会根据配置的类所在的包,为包和子包进行扫描装配对应配置的Bean.
  • 使用接口编写操作类是Spring推荐的,可以将定义与实现分离,这样就更加灵活
      在这里插入图片描述
  • 这里的@Component表明ScanImpl是一个Spring需要的Bean,并且实现了Scan接口的方法,但是该方法中需要接收一个User类的对象,因此还需要进行配置User
      在这里插入图片描述
  • 最后就是指定扫描了,这里使用了@ComponentScan的两个配置项,精确扫描类和包,然后进行测试即可
      在这里插入图片描述
      在这里插入图片描述
  • 关于basePackages和basePackageClasses的选择,前者的可读性会更好一点.

5.4 使用@Autowired自动装配

  • 之前提到的注解没有注入对象的问题,可以使用自动装配进行解决,可以减少配置的复杂度.
  • 关于@Autowired的工作原理:Spring完成Bean的定义和生成之后,会去寻找需要注入的资源.也就是当Spring生成所有Bean之后,如果发现@Autowired注解,就会在SpringIOC容器中的Bean中查找,找到对应类型后,便将其注入到标注了@Autowired注解的对象上(注意这里也有多态的产生,比如标注了注解的是一个父类或者接口,那么SpringIOC自动注入的Bean实例可以是子类或者实现类),这样就完成了依赖注入.
  • 通过代码进行演示—对5.3中的代码进行部分修改即可
      在这里插入图片描述
      在这里插入图片描述
  • 在ScanImpl中的@Autowired注解,表示在SpringIOC定位了所有的Bean之后,这个字段需要按照类型进行注入,这样SpringIOC容器就会寻找资源,然后将其注入.
  • 但是有时候IoC容器也会寻找失败,在默认情况下寻找失败会抛出异常.也就是说,默认情况下,SpringIOC容器会认为一定要找到对应的Bean来注入这个字段,但是有时候,等待被注入的对象可能不一定是必须的,也就是说使用@Autowired注解的属性就算没有被自动注入也没有关系,那么我们就可以使用@Autowired的配置项required来改变它,比如@Autowired(required=false)
  • 默认情况下使用@Autowired是必须注入成功的,也就是说默认required为true.当改为false之后,就相当于告诉SpringIOC容器,如果在容器中的Bean中找不到对应类型,允许不注入,也不会产生异常.绝大部分情况下,不需要进行修改.
      比如我们将上面案例中的User类上的@Component注释掉,重新运行
      在这里插入图片描述
      在这里插入图片描述
      依旧注释User的@Component注解,但是将ScanImpl中的属性的@Autowired设为required=false
      在这里插入图片描述
      在这里插入图片描述
  • @Autowired还可以配置在方法上,常见Bean的setter方法也是用它完成注入
      在这里插入图片描述
  • 大部分情况下,是极力推荐使用@Autowired注解,这是SpringIOC自动装配完成的,使得配置大幅度减少,满足约定优于配置的原则,增强程序的健壮性.
  • 但是有时候不能进行自动装配.看Next↓↓↓

5.5 @Autowired的缺陷

  • 细心的小伙伴可能注意到了我5.4里面提到的多态的问题,@Autowired注解固然很方便,可以自动装配,使用很简单,但是有些地方却不能使用—>根源在于@Autowired是按类型进行匹配的.
  • 按照Spring的建议,大部分情况下都会使用接口编程,但是定义一个接口,仅仅会只有一个实现类吗?答案是不会的.之前的例子中Scan接口完全可以有ScanImpl1,ScanImpl2,ScanImpl3等实现类.
      在这里插入图片描述
  • 新建一个TestScan类,有个字段是ScanImpl类型的
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 这时候SpringIOC容器就糊涂了,因为有两个Scan接口的实现类都放入了SpringIOC容器中,@Autowired根据类型进行注入时,找不到唯一一个Bean实例,所以就抛出了异常,这时候注入就失败了
  • 分析一下注入失败的原因:@Autowired是通过类型匹配注入对象的,而java接口可有多个实现类,同样抽象类也可以有多个实例化的类,这样就会造成类型获取Bean的不唯一性,从而导致SpringIOC容器无法得到唯一的实例化类.
  • 回想一下第一篇文章的内容—>Spring学习(一),BeanFactory中进行获取Bean的方法有一个getBean(Class requiredType) 也是通过类型获取,当时我也说过这种方式在容器中同时存在多个同类型的Bean时就会报错.

5.6 解决@Autowired缺陷方式一–@Primary

  • 注解@Primary代表是首要的,当SpringIOC通过一个接口或者抽象类注入对象时,由于存在多个实现类或具体类,就会出错,不知道该采用哪个类.注解@Primary则是告诉SpringIOC容器,请优先使用该类注入.
      在这里插入图片描述
      在这里插入图片描述
  • 上面情况就是将ScamImpl1作为首要的,如果存在两个及其以上的实现类都使用@Primary注解,那么依旧会抛出异常.
  • @Primary注解只能解决首要性问题,不能解决选择性问题.它无法选择接口具体的哪个实现类去注入

5.7 解决@Autowired缺陷方式二–@Qualifier

  • 上面提及到@Autowired产生的歧义性,一个重要原因在于Spring寻找依赖注入的时候采用按类型注入引起的,除了按类型查找Bean,SpringIOC容器最底层接口BeanFactory,也定义了按名称查找的方法,如果采用按名称查找的方法,那不就可以消除这种歧义性了吗?,答案是肯定的.注解@Qualifier就是起到这样的作用
  • 现在让我们对Scan接口的两个实现类分别起不同的名称
      在这里插入图片描述
  • 在TestScan中的待注入的属性中,我们使用@Qualifier按名称指定注入
      在这里插入图片描述
      在这里插入图片描述
  • 这时IoC容器就不会按照类型的方式去注入了,而是按照名称的方式去注入,这样就能注入成功,也消除了歧义性.IoC容器底层接口—BeanFactory,它所定义的方法:Object getBean(String name),使用@Qualifier注解后就可以使用这个方法从IoC容器中获取对象进行注入

5.8 装载带有参数的构造方法类

  • 新建一个User类,使其构造方法是含有参数的,含有的参数类型是Address类型,之前使用xml给Bean通过构造器注入已经说过了,现在谈一下注解注入.
      
  • 我们可以使用@Autowired注解进行注入,该注解可以注解属性和方法
  • 测试
      在这里插入图片描述
      在这里插入图片描述

5.9 使用@Bean装配Bean

  • 以上都是使用@Component进行装配Bean,但是@Component只能注解在类上,不能注解到方法上.对于Java而言,大部分开发都需要引入第三方jar包,并且经常需要将他们作为开发环境的Bean来使用.可以使用@Bean注解,它可以注解到方法上,并且将方法返回值的对象作为Spring的Bean,存放在SpringIOC容器中.
  • 比如我们现在要使用一个数据库连接源的配置信息
      在这里插入图片描述
  • 该方法的返回值就将自动放入SpringIOC容器中,且名称指定为properties,该名称将作为Bean的id值.这样这个Bean就可以被其他需要的地方所引用了

6 装配的混合使用

  • 这一部分没有什么太多总结的知识,主要就是侧重于实践中的使用,等后面更新完SpringMvc和MyBatis,你就会感到混合使用是很常见的事情,能用注解的尽量用注解,因为这会使你的代码变得更简单,而引入第三方工具经常还是需要借助于xml的配置
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值