热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Spring第七篇:依赖的自动注入

Spring的依赖的手动注入,手动注入是在bean.xml文件中通过硬编码的形式,通过参数构造器的construct-arg方式或者setter方法的property方式来进行依赖

  Spring的依赖的手动注入,手动注入是在bean.xml文件中通过硬编码的形式,通过参数构造器的construct-arg方式或者setter方法的property方式来进行依赖的注入,存在明显的不足:

  bean实例中依赖的属性较多时,bean.xml文件中配置元数据信息会相应暴增,而且对bean实例所属的类中进行修改,则需要对对应的bean.xml配置文件进行调整。使用手动注入的方式进行依赖管理,不利于代码的维护与扩展

  Class.isAssignableFrom方法  

  Class1.isAssignableFrom (Class2)调用者和参数都是 java.lang.Class 类型,用来判断Class1与Class2相同,或者Class1是否是Class2的超类。

  test方法


@Test
public void test(){
System.out.println(List.
class.isAssignableFrom(List.class));//true
System.out.println(List.class.isAssignableFrom(int.class));//false
System.out.println(List.class.isAssignableFrom(Object.class));//false
System.out.println(Object.class.isAssignableFrom(List.class));//true
}

  Spring的自动注入:

  自动注入是采用约定大约配置的方式来实现的,程序和spring容器之间约定好,遵守某一种都认同的规则,来实现自动注入。xml中可以在bean元素中通过autowire属性来设置自动注入的方式:


class="X类" autowire="byName|byType|constructor|default"/>

  一、byName(通过名称注入)

  创建class类型


public class AutowiredByName {
private Service1 service1;
private Service2 service2;
public AutowiredByName() {
}
public AutowiredByName(Service1 service1, Service2 service2) {
this.service1 = service1;
this.service2 = service2;
}
public Service1 getService1() {
return service1;
}
public void setService1(Service1 service1) {
this.service1 = service1;
}
public Service2 getService2() {
return service2;
}
public void setService2(Service2 service2) {
this.service2 = service2;
}
@Override
public String toString() {
return "AutowiredByName{" +
"service1=" + service1 +
", service2=" + service2 +
‘}‘;
}
//定义内部类
public static class Service1{
private String desc;
public Service1() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service1{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
public static class Service2{
private String desc;
public Service2() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service2{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
}

  bean.xml文件增加配置



class="com.java.spring01.demo5.AutowiredByName.Service1">


class="com.java.spring01.demo5.AutowiredByName.Service2">



class="com.java.spring01.demo5.AutowiredByName" autowire="byName"/>

   运行test方法


@Before
public void before(){
String beanXML
= "classpath:/spring01/demo5/bean.xml";
context
= new ClassPathXmlApplicationContext(beanXML);
}
@Test
public void test1(){
Object autowiredByName
= context.getBean("autowiredByName");
if( AutowiredByName.class.isAssignableFrom(autowiredByName.getClass())){
System.out.println(autowiredByName);
}
}

  test方法运行结果


AutowiredByName{service1=Service1{desc=‘byName-service1‘}, service2=Service2{desc=‘byName-service2‘}}

  Spring容器创建autowried对象的时候,会遍历AutowiredByName类中的所有属性,得到service1、service2的属性列表。然后根据属性名在Spring容器中获取到相应的bean对象,调用AutowiredByName类的set方法将其注入到autowried的bean对象中。注入的时候会校验service1和service2的类型和AutowiredByName类中的属性类型是否一一对应。不对应会报出错误:


Caused by: java.lang.IllegalStateException: Cannot convert value of type

  二、byType(根据类型注入)

  Spring根据类型注入的时候会解析属性的类型然后调用set方法进行注入,当bean.xml文件中不存在对应类型的bean时,则不进行注入,若是多个相同类型的bean存在则会直接在xml文件中提示more than one bean of....

  创建class类型


public class AutowiredByType {
private Service1 service1;
private Service2 service2;
public AutowiredByType() {
}
public AutowiredByType(Service1 service1, Service2 service2) {
this.service1 = service1;
this.service2 = service2;
}
public Service1 getService1() {
return service1;
}
public void setService1(Service1 service1) {
this.service1 = service1;
}
public Service2 getService2() {
return service2;
}
public void setService2(Service2 service2) {
this.service2 = service2;
}
@Override
public String toString() {
return "AutowiredByType{" +
"service1=" + service1 +
", service2=" + service2 +
‘}‘;
}
//定义内部类
public static class Service1{
private String desc;
public Service1() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service1{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
public static class Service2{
private String desc;
public Service2() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service2{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
}

  bean.xml文件中增加配置



class="com.java.spring01.demo5.AutowiredByType.Service1">


class="com.java.spring01.demo5.AutowiredByType.Service2">


class="com.java.spring01.demo5.AutowiredByType" autowire="byType"/>

  test方法


  @Test
public void test2(){
System.out.println(context.getBean(
"autowiredByType"));
}

  test方法运行结果


AutowiredByType{service1=Service1{desc=‘byType-service1‘}, service2=Service2{desc=‘byType-service2‘}}


  注入类型匹配的所有bean(重点)

  按照类型注入还有2中比较牛逼的用法:



  • 一个容器中满足某种类型的bean可以有很多个,将容器中某种类型中的所有bean,通过set方法注入给一个java.util.List<需要注入的Bean的类型或者其父类型或者其接口>对象



  • 将容器中某种类型中的所有bean,通过set方法注入给一个java.util.Map对象



  三、constructor(构造函数注入)

  Spring会将类的所有构造函数筛选出来,将所有的构造函数进行排序(public的在前面,参数数量多的在前面),然后根据bean.xml中的配置文件采用贪婪原则进行匹配,尽可能多注入依赖的bean。

  创建class对象


public class AutowiredByConstructor {
private Service1 service1;
private Service2 service2;
private Service3 service3;
public AutowiredByConstructor(Service1 service1) {
this.service1 = service1;
}
public AutowiredByConstructor(Service1 service1, Service2 service2, Service3 service3) {
this.service1 = service1;
this.service2 = service2;
this.service3 = service3;
}
//静态内部类
public static class Service1{
private String desc;
public Service1(String desc) {
this.desc = desc;
}
public Service1() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service1{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
public static class Service2{
private String desc;
public Service2(String desc) {
this.desc = desc;
}
public Service2() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service2{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
public static class Service3{
private String desc;
public Service3(String desc) {
this.desc = desc;
}
public Service3() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
@Override
public String toString() {
return "Service3{" +
"desc=‘" + desc + ‘\‘‘ +
‘}‘;
}
}
@Override
public String toString() {
return "AutowiredByConstructor{" +
"service1=" + service1 +
", service2=" + service2 +
", service3=" + service3 +
‘}‘;
}
}

  更改bean.xml,增加配置元数据信息


class="com.java.spring01.demo5.AutowiredByConstructor.Service1">


class="com.java.spring01.demo5.AutowiredByConstructor.Service2">


class="com.java.spring01.demo5.AutowiredByConstructor.Service3">


class="com.java.spring01.demo5.AutowiredByConstructor" autowire="constructor"/>

  运行test方法及运行结果


@Test
public void test3(){
System.out.println(context.getBean(
"autowiredByConstructor"));
}


AutowiredByConstructor{service1=Service1{desc=‘constructor-service1‘}, service2=Service2{desc=‘constructor-service2‘}, service3=Service3{desc=‘constructor-service3‘}} 

  注意AutowiredByConstructor 类中有两个带参的构造函数,一个只需要Service1的参数,另一个需要全部的参数,当我们在bean.xml文件中将Service3的bean注释掉。则Spring容器创建对象的时候调用的是只有一个参数的构造函数。若是同一属性存在多个bean的话,则会跳过带有这个跟这些bean类型的参数的构造函数。

   四、default(byType|byName|constructor)

  bean.xml文件中的根元素beans中存在属性default-autowire,往这个属性上设置byType|byName|constructor值,就可以在bean中使用上autowired属性。


推荐阅读
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了一种解析GRE报文长度的方法,通过分析GRE报文头中的标志位来计算报文长度。具体实现步骤包括获取GRE报文头指针、提取标志位、计算报文长度等。该方法可以帮助用户准确地获取GRE报文的长度信息。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
author-avatar
as8244433
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有