精华内容
下载资源
问答
  • 2019-06-03 14:33:44

    Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入(Construct注入),setter注入,基于注解的注入(接口注入)。(参考https://blog.csdn.net/jinchaoh/article/details/80246577

    构造方法注入

    如果只有一个有参数的构造方法并且参数类型与注入的bean的类型匹配,那就会注入到该构造方法中。

    Setter注入

    在XML中写入,然后在set方法中注入。示

    例如下:

    <!-- 注册userService -->
    <bean id="userService" class="com.lyu.spring.service.impl.UserService">
        <!-- 写法一 -->
        <!-- <property name="UserDao" ref="userDaoMyBatis"></property> -->
        <!-- 写法二 大小写无所谓,因为Spring会将每个单词首字母自动改为大写-->
        <property name="userDao" ref="userDaoMyBatis"></property>
    </bean>
     
    <!-- 注册mybatis实现的dao -->
    <bean id="userDaoMyBatis" class="com.lyu.spring.dao.impl.UserDaoMyBatis"></bean>

    然后在set中使用

    public class UserService implements IUserService {
     
        private IUserDao userDao1;
     
        public void setUserDao(IUserDao userDao1) {//这里注意,name方法与类中成员变量名和方法的参数名都无关,只与set方法名有关
            this.userDao1 = userDao1;
        }
     
        public void loginUser() {
            userDao1.loginUser();
        }
     
    }

    如果通过set方法注入属性,那么spring会通过默认的空参构造方法来实例化对象,所以如果在类中写了一个带有参数的构造方法,一定要把空参数的构造方法写上(必须要有空参构造方法),否则spring没有办法实例化对象,导致报错。 


    基于注解的注入

    @Autowired(自动注入)修饰符有三个属性:Constructor,byType,byName。默认按照byType注入。

    constructor:通过构造方法进行自动注入,spring会匹配与构造方法参数类型一致的bean进行注入,如果有一个多参数的构造方法,一个只有一个参数的构造方法,在容器中查找到多个匹配多参数构造方法的bean,那么spring会优先将bean注入到多参数的构造方法中。

    byName:被注入bean的id名必须与set方法后半截匹配,并且id名称的第一个单词首字母必须小写,这一点与手动set注入有点不同。
    byType:查找所有的set方法,将符合符合参数类型的bean注入。

    主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有所差异:

    1. @Component:可以用于注册所有bean
    2. @Repository:主要用于注册dao层的bean
    3. @Controller:主要用于注册控制层的bean
    4. @Service:主要用于注册服务层的bean

    在写DAO函数的时候,一般要写一个@Mapper,作用为:(参考https://blog.csdn.net/weixin_39666581/article/details/81057385

    1:为了把mapper这个DAO交给Spring管理 

    2:为了不再写mapper映射文件

    3:为了给mapper接口 自动根据一个添加@Mapper注解的接口生成一个实现类

     

    更多相关内容
  • 主要介绍了Spring依赖注入三种方式的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下
  • 本篇文章主要介绍了spring四种依赖注入方式的详细介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Spring依赖注入方式

    2019-04-19 01:40:32
    NULL 博文链接:https://huangminwen.iteye.com/blog/1041743
  • spring依赖注入三种方式以及优缺点 一.依赖注入三种方式 1.通过构造器注入。(spring4.3之后,推荐使用) 2.通过setter注入。(spring4.3之前,推荐使用) 3通过filed注入。 二.三种方式的代码示例: ...

    spring依赖注入的三种方式以及优缺点

    一.依赖注入的三种方式

    1.通过构造器注入。(spring4.3之后,推荐使用)

    2.通过setter注入。(spring4.3之前,推荐使用)

    3通过filed注入。

    二.三种方式的代码示例:

    Constructor注入

        private AlarmContactService alarmContactService;
    
    	private final AlarmService alarmService;
    
    	private final SysUserService sysUserService;
    
        @Autowired
    	public AlarmContactController(AlarmContactService alarmContactService, AlarmService alarmService,
    			SysUserService sysUserService) {
    		this.alarmContactService = alarmContactService;
    		this.alarmService = alarmService;
    		this.sysUserService = sysUserService;
    	}

    Setter注入

    private AlarmContactService alarmContactService;
    
    	private AlarmService alarmService;
    
    	private SysUserService sysUserService;
    
    	@Autowired
    	public void setAlarmContactService(AlarmContactService alarmContactService) {
    		this.alarmContactService = alarmContactService;
    	}
    
    	@Autowired
    	public void setAlarmService(AlarmService alarmService) {
    		this.alarmService = alarmService;
    	}
    
    	@Autowired
    	public void setSysUserService(SysUserService sysUserService) {
    		this.sysUserService = sysUserService;
    	}

    Field注入

        @Autowired
    	private AlarmContactService alarmContactService;
    
    	@Autowired
    	private AlarmService alarmService;
    
    	@Autowired
    	private SysUserService sysUserService;

    三.3种方式的各优点和缺点

    三种方式的优点分析

    1.基于构造器注入,会固定依赖注入的顺序,不允许我们创建的bean对象之间存在循环依赖关系,这样Spring能解决循环依赖的问题。

    2.基于setter注入,只有对象是需要被注入的时候,才会注入依赖,而不是在初始化的时候就注入。

    3.在成员变量上写上注解来注入,这种方式,精短,可读性高,不需要多余的代码,也方便维护。

    三种方式的缺点分析

    1.使用构造器注入的缺点是,当我们构造器需要注入的对象比较多时,会显得我们的构造器,冗余,不美观,可读性差,也不易维护。

    2.当我们选择setter方法来注入的时候,我们不能将对象设为final的;

    3.当我们在field变量上来实现注入的时候

        a.这样不符合JavaBean的规范,而且很有可能引起空指针;

        b.同时也不能将对象标为final的;

      c.类与DI容器高度耦合,我们不能在外部使用它;

        d.类不通过反射不能被实例化(例如单元测试中),你需要用DI容器去实例化它,这更像集成测试;

     

    来自Spring官方文档的建议:  
    在Spring 3.x 中,Spring团队建议我们使用setter来注入:

    而在Spring 4.x 中,Spring团队不再建议我们使用setter来注入,改为了constructor:

    Spring团队通常建议使用构造器来注入,因为它允许一个应用程序组件实现为不可变对象,并确保所需的依赖项不是空。此外构造器注入组件总是返回一个完全初始化状态的client客户端(调用)。附注,大量的构造函数参数是一个糟糕的代码习惯,看起来也很坏,这意味着类可能有太多的责任,应该被重构,以更好地解决适当的关注点分离。

     

    三.解释下什么是循环依赖:

    1. 循环依赖是什么?

    Bean A 依赖 B,Bean B 依赖 A这种情况下出现循环依赖。

    Bean A → Bean B → Bean A     或者 Bean A → Bean B → BeanC → Bean A

    2. 循环依赖会产生什么结果?

    当Spring正在加载所有Bean时,Spring尝试以能正常创建Bean的顺序去创建Bean。

    例如,有如下依赖:

    Bean A → Bean B → Bean C

    Spring先创建beanC,接着创建bean B(将C注入B中),最后创建bean A(将B注入A中)。

    假如,有如下循环依赖:

    Bean A → Bean B → Bean C → BeanD → Bean A  

     

    但当存在循环依赖时,Spring将无法决定先创建哪个bean。这种情况下,Spring将产生异常BeanCurrentlyInCreationException。

     

    一条Spring 4.3 的新特征:

    在Spring 4.3 以后,如果我们的类中只有单个构造函数,那么Spring就会实现一个隐式的自动注入:

    就是我去掉了构造器上的@Autowired注解,经测试后发现,程序能正常运行。alarmContactService,alarmService,sysUserService的依赖也被成功注入了。

        private AlarmContactService alarmContactService;
    
    	private final AlarmService alarmService;
    
    	private final SysUserService sysUserService;
    
    	public AlarmContactController(AlarmContactService alarmContactService, AlarmService alarmService,
    			SysUserService sysUserService) {
    		this.alarmContactService = alarmContactService;
    		this.alarmService = alarmService;
    		this.sysUserService = sysUserService;
    	}

    使用构造注入允许加入final,这也表示以后不能再被更改了。

     

     

    展开全文
  • Spring系列之依赖注入三种方式

    千次阅读 2019-05-22 10:13:39
    一、依赖注入方式 1.使用属性的setXXX方法注入 2.构造函数注入 (1)按类型匹配入参type (2)按索引匹配入参index (3)联合使用类型和索引匹配入参[type和index一起使用] 有时需要联合使用type和index才能...

    目录

    一、依赖注入方式

    1.使用属性的setXXX方法注入

     2.构造函数注入

    (1)按类型匹配入参type

    (2)按索引匹配入参index

    (3)联合使用类型和索引匹配入参[type和index一起使用]     有时需要联合使用type和index才能确定匹配项和构造函数入参的对应关系,看下面的代码。

    二、依赖注入的本质就是装配——自动装配:spring可以使用xml和注解来进行自动装配。自动装配就是开发人员不必知道具体要装配哪个bean的引用,这个识别的工作会由spring来完成,自动装配就是为了将依赖注入“自动化”的一个简化配置的操作

    2.1 自动装配的概念

    2.2 通过xml配置的方式实现自动装配

    2.2.1 装配分为四种:byName, byType, constructor, autodetect。

    2.3 spring2.5之后提供了注解方式的自动装配。

    2.3.1 常用的自动装配注解有以下几种:@Autowired,@Qualifier,@Named,@Resource,@Inject。

    2.4  自动检测配置,也是springmvc中最牛的一项功能:只要一个配置,base-package属性指定要自动检测扫描的包。


    转载:Spring系列之依赖注入的方式

    转载:傻傻分不清:Spring IoC注入,自动装配与循环依赖

    一、依赖注入方式

          对于spring配置一个bean时,如果需要给该bean提供一些初始化参数,则需要通过依赖注入方式,所谓的依赖注入就是通过spring将bean所需要的一些参数传递到bean实例对象的过程(将依赖关系注入到对象中),spring的依赖注入有3种方式:

    ·使用属性的setter方法注入 ,这是最常用的方式;
    ·使用构造器注入;

     最好的解决方案是用构造器参数实现强制依赖,setter 方法实现可选依赖。

    1.使用属性的setXXX方法注入

         属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。

    <bean id=”……” class=”……”>  
        <property name=”属性1” value=”……”/>  
        <property name=”属性2” ref=”……”/>  
        ……  
    </bean> 

          属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。来看一个简单的例子。

    package com.spring.model;
    
    public class Car {
        
        private int maxSpeed;
        private String brand;
        private double price;
        
        public int getMaxSpeed() {
            return maxSpeed;
        }
        //一定要写被注入对象的set方法
        public void setMaxSpeed(int maxSpeed) {
            this.maxSpeed = maxSpeed;
        }
        public String getBrand() {
            return brand;
        }
        public void setBrand(String brand) {
            this.brand = brand;
        }
        public double getPrice() {
            return price;
        }
        public void setPrice(double price) {
            this.price = price;
        }
        
        public void run(){
            System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price);
        }
    }
    

       Car类中定义了3个属性,并分别提供了对应的Setter方法。(注:默认构造函数是不带参的构造函数。Java语言规定如果类中没有定义任何构造函数,则JVM自动为其生成一个默认的构造函数。反之,如果类中显示定义了构造函数,则JVM不会为其生成默认的构造函数。所以假设Car类中显示定义了一个带参的构造函数,如public Car(String brand),则需要同时提供一个默认构造函数public Car(),否则使用属性注入时将抛出异常。)

    下面在Spring配置文件中对Car进行属性注入:

    <!-- 属性注入 -->
    <bean id="car" class="com.spring.model.Car">  
        <property name="maxSpeed" value="200"></property>
        <property name="brand" value="红旗CA72"></property>  
        <property name="price" value="200000.00"></property>
    </bean>

         在上述代码中配置了一个Bean,并为该Bean的3个属性提供了属性值。具体来说,Bean的每一个属性对应一个<property>标签,name为属性的名称,在Bean实现类中拥有与其对应的Setter方法:maxSpeed对应setMaxSpeed(),brand对应setBrand()。
         需要指出的是:Spring只会检查Bean中是否有对应的Setter方法,至于Bean中是否有对应的属性变量则不做要求。例如配置文件中<property name="brand"/>的属性配置项仅要求Car类中拥有setBrand()方法,但Car类不一定要拥有brand成员变量。

     2.构造函数注入

    构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到设置(construct是bean生命周期的第一步,实例化bean),并且确保了Bean实例在实例化后就可以使用。

    使用方式:

    第一,在类中,不用为属性设置setter方法(但是可以有),但是需要生成该类带参的构造方法。

    第二,在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了<constructor-arg>节点,该节点有四个属性:

    · index是索引,指定注入的属性位置,从0开始;

    · type是指该属性所对应的类型;

    · ref 是指引用的依赖对象;

    · value 当注入的不是依赖对象,而是基本数据类型时,就用value;

    (1)按类型匹配入参type

          如果任何可用的Car对象都必须提供maxSpeed、brand和price的值,使用属性注入方式只能人为在配置时提供保证,而无法在语法级提供保证,这时通过构造函数注入就可以很好地满足这一要求。使用构造函数注入的前提是Bean必须提供带参的构造函数,下面为Car提供一个可设置maxSpeed、brand和price属性的构造函数。

    package com.spring.model;
    
    public class Car {
        
        private int maxSpeed;
        private String brand;
        private double price;
        
        //带参构造方法
        public Car(int maxSpeed,String brand, double price){
            this.maxSpeed=maxSpeed;
            this.brand=brand;
            this.price=price;
        }
        
        public void run(){
            System.out.println("brand:"+brand+",maxSpeed:"+maxSpeed+",price:"+price);
        }
    }

    构造函数注入的配置方式和属性注入方式的配置有所不同,在spring配置文件中使用构造函数注入装配这个Car Bean。

    <!-- 构造函数注入(按类型匹配) -->
    <bean id="car1" class="com.spring.model.Car">  
        <constructor-arg type="int" value="300"></constructor-arg>
        <constructor-arg type="java.lang.String" value="宝马"></constructor-arg>
        <constructor-arg type="double" value="300000.00"></constructor-arg>
    </bean>

    在<constructor-arg>的元素中有一个type属性,它表示构造函数中参数的类型,为spring提供了判断配置项和构造函数入参对应关系的“信息”。

    (2)按索引匹配入参index

          我们知道,Java语言通过入参的类型及顺序区分不同的重载方法,对于上面代码中的Car类,Spring仅通过type属性指定的参数类型就可以知道“宝马”对应String类型的brand入参,而“300000.00”对应double类型的price入参。但是,如果Car构造函数3个入参的类型相同,仅通过type就无法确定对应关系了,这时需要通过入参索引的方式进行确定。
    为了更好地演示按索引匹配入参的配置方式,特意对Car构造函数进行一下调整。

    public Car(String brand, String corp,double price){
        this.brand=brand;
        this.corp=corp;
        this.price=price;
    }

    brand和corp的入参类型都是String,所以String将无法确定type为String的<constructor-arg>到底对应的是brand还是corp。但是,通过显示指定参数的索引能够消除这种不确定性,如下所示。

    <!-- 构造函数注入(按索引匹配) -->
    <bean id="car2" class="com.spring.model.Car"> 
        <!-- 注意索引从0开始 --> 
        <constructor-arg index="0" value="宝马"></constructor-arg>
        <constructor-arg index="1" value="中国一汽"></constructor-arg>
        <constructor-arg index="2" value="300000.00"></constructor-arg>
    </bean>

    构造函数第一个参数索引为0,第二个为1,以此类推,因此很容易知道“宝马”对应brand入参,而“中国一汽”对应corp入参。

    (3)联合使用类型和索引匹配入参[type和index一起使用]
         有时需要联合使用type和index才能确定匹配项和构造函数入参的对应关系,看下面的代码。

    public Car(String brand, String corp,double price){
        this.brand=brand;
        this.corp=corp;
        this.price=price;
    }
    
    public Car(String brand, String corp,int maxSpeed){
        this.brand=brand;
        this.corp=corp;
        this.maxSpeed=maxSpeed;
    }

         这里,Car拥有两个重载的构造函数,它们都有三个入参。针对这种情况,按照入参索引的配置方式又难以满足要求了,这时需要联合使用<constructor-arg>的type和index才能解决问题,看下面代码。

    <!-- 构造函数注入(通过入参类型和位置索引确定对应关系) -->
    <!-- 对应public Car(String brand, String corp,int maxSpeed)构造函数 -->
    <bean id="car3" class="com.spring.model.Car">  
        <constructor-arg index="0" type="java.lang.String" value="奔驰"></constructor-arg>
        <constructor-arg index="1" type="java.lang.String" value="中国一汽"></constructor-arg>
        <constructor-arg index="2" type="int" value="200"></constructor-arg>
    </bean>

          对于上面的两个构造函数,如果仅通过index进行配置,Spring将无法确定第3个入参配置项究竟是对应int的maxSpeed还是double的price,采用索引匹配时,真正引起歧义的地方在于第3个入参,因此仅需要明确指定第3个入参的类型就可以取消歧义了。所以在上面的代码中,第1个和第2个<constructor-arg>元素的type属性可以去除。
          对于由于参数数目相同而类型不同所引起的潜在配置歧义问题,Spring容器可以正确启动且不会给出报错信息,它将随机采用一个匹配的构造函数实例化Bean,而被选择的构造函数可能并不是用户所希望的。因此,必须特别谨慎,以避免潜在的错误。

    二、依赖注入的本质就是装配——自动装配:spring可以使用xml和注解来进行自动装配。自动装配就是开发人员不必知道具体要装配哪个bean的引用,这个识别的工作会由spring来完成,自动装配就是为了将依赖注入“自动化”的一个简化配置的操作

    2.1 自动装配的概念

    大家可以看到用xml装配bean是一件很繁琐的事情,而且我们还要找到对应类型的bean才能装配。

    创建应用对象之间协作关系的行为称为装配。也就是说当一个对象的属性是另一个对象时,实例化时,需要为这个对象属性进行实例化,这就是装配。

    如果一个对象只通过接口来表明依赖关系,那么这种依赖就能够在对象本身毫不知情的情况下,用不同的具体实现进行切换。但是这样会存在一个问题,在传统的依赖注入配置中,我们必须要明确要给属性装配哪一个bean的引用,一旦bean很多,就不好维护了。基于这样的场景,spring使用注解来进行自动装配,解决这个问题。自动装配就是开发人员不必知道具体要装配哪个bean的引用,这个识别的工作会由spring来完成。

    与自动装配配合的还有“自动检测”,这 个动作会自动识别哪些类需要被配置成bean,进而来进行装配。这样我们就明白了,自动装配是为了将依赖注入“自动化”的一个简化配置的操作。

    2.2 通过xml配置的方式实现自动装配

    2.2.1 装配分为四种:byName, byType, constructor, autodetect。

    具体选择哪一种装配方式,需要配置<bean>标签的autowire属性,如果没有配置,默认是byName类型,就是会根据属性的名字来进行自动装配。

    1)byName就是会将与属性的名字一样的bean进行装配。

    2)byType就是将同属性一样类型的bean进行装配。

    3)constructor就是通过构造器来将类型与参数相同的bean进行装配。

    4)autodetect是constructor与byType的组合,会先进行constructor,如果不成功,再进行byType。

    上面最常用的还是byName和byType。自动装配时,装配的bean必须是唯一与属性进行吻合的,不能多也不能少,有且只有一个可以进行装配的bean,才能自动装配成功。否则会抛出异常。如果要统一所有bean的自动装配类型,可以在<beans>标签中配置default-autowire属性。当然如果配置了autowire属性,我们依然可以手动装配属性,手动装配会覆盖自动装配。

    2.3 spring2.5之后提供了注解方式的自动装配。

    但是要使用这些注解,需要在配置文件中配置<context:annotation-config />。只有加上这一配置,才可以使用注解进行自动装配,默认情况下基于注解的装配是被禁用的

    2.3.1 常用的自动装配注解有以下几种:@Autowired,@Qualifier,@Named,@Resource,@Inject。

    1)@Autowired注解是byType类型的,这个注解可以用在属性上面,setter方面上面以及构造器上面。

    • 使用这个注解时,就不需要在类中为属性添加setter方法了。但是这个属性是强制性的,也就是说必须得装配上,如果没有找到合适的bean能够装配上,就会抛出异常NoSuchBeanDefinitionException。这时可以使用required=false来允许可以不被装配上,如果required=false时,则不会抛出异常。另一种情况是同时有多个bean是一个类型的,也会抛出这个异常。此时需要进一步明确要装配哪一个Bean,这时可以组合使用@Qualifier注解,值为Bean的名字即可。

    2)@Qualifier注解使用byName进行装配,这样可以在多个类型一样的bean中,明确使用哪一个名字的bean来进行装配。@Qualifier注解起到了缩小自动装配候选bean的范围的作用。

    • 注意:@Autowired注解是spring提供的,所以会依赖spring的包。还有一个byType的注解@Inject,与@Autowired注解作用一样,也是byType类型,而且是java ee提供的,完全可以代替@Autowired注解,但是@Inject必须是强制装配的,没有required属性,也就是不能为null,如果不存在匹配的bean,会抛出异常。@Autowired与@Qualifier可以组合使用,@Inject也有一个组合的注解,就是@Named注解,与@Qualifier作用一样,也是byName,但是不是spring的,是java ee标准的。这样就出现了两套自动装配的注解组合,@Autowired与@Qualifier是spring提供的,@Inject与@Named是java ee的。但是@Qualifier注解在java ee中也有一样,作用与spring的@Qualifier注解一模一样,只是所在的包不一样。不过建议大家使用spring的。最后还有一个@Resouce注解, 这个注解也是java ee的,也是byName类型的,原理同@Qualifier和@Named是一样的。

    2.4  自动检测配置,也是springmvc中最牛的一项功能:只要一个配置<context:component-scan base-package="">,base-package属性指定要自动检测扫描的包。

    该配置会自动扫描指定的包及其子包下面被构造型注解标注的类,并将这些类注册为spring bean,这样就不用在配置文件一个一个地配置成bean标签。构造型注解包括:@Controller,@Component,@Service,@Repositoryt标注的自定义注解。

    生成的bean的ID默认为类的非限定名,也就是把类的名字的首字母换成小写。可以在这些注解的值中写名bean id的值,如@Controller("helloworld")。如果你想细化包被扫描的范围,可以使用<context:include-filter>和<context:exclude-filter>。具体使用方法这里不再详说。注意,没有被扫描到的类是不能注册为bean,也就不能被用来装配其他类。所以这个配置的base-package的范围非常重要。

     

     

    展开全文
  • Spring支持两种依赖注入方式,分别是属性注入,构造函数注入。除此之外,Spring还支持工厂注入方式。 接下来,我们一起来了解一下Spring的几注入方式。 一.属性注入 首先来了解一下定义:属性注入是指通过 ...

     

    搬砖啦,搬砖啦,这几天在看Spring相关的书,下面给大家分享一下这几天的心得与收获,Go Go Go!


    Spring支持两种依赖注入方式,分别是属性注入,构造函数注入。除此之外,Spring还支持工厂注入方式。

    接下来,我们一起来了解一下Spring的几种注入方式。


    一.属性注入

    首先来了解一下定义属性注入是指通过 setXxx()方法注入Bean的属性或依赖对象。

    为什么要使用: 因为属性注入方式具有可选择性和高灵活性的特点,所以属性注入方式是实际应用中最常采用的注入方式。

    来来来,直接上代码!

    造个Car实体类

    Car类中定义了3个属性,并分别提供了对应的Setter方法

    package com.vtstar.entity;
    
    /**
     * @ClassName Car
     * @Description TODO
     * @Author XiaoWu
     * @Date 2018/9/6 9:53
     * @Version 1.0
     **/
    public class Car {
    
        private int maxSpeed;
    
        public String brand;
    
        private double price;
    
        private Boss boss;
    
        public Car() {
        }
    
        public Car(double price, Boss boss) {
            System.out.println("I'm the Car's construct two " + price + " boss " + boss.getName());
            this.price = price;
            this.boss = boss;
        }
    
        public Car(int maxSpeed, String brand, double price) {
            System.out.println("车的时速是" + maxSpeed + " 品牌为:" + brand + " 价格为:" + price);
            this.maxSpeed = maxSpeed;
            this.brand = brand;
            this.price = price;
        }
    
        public int getMaxSpeed() {
            return maxSpeed;
        }
    
        public void setMaxSpeed(int maxSpeed) {
            System.out.println("The maximum speed is " + maxSpeed);
            this.maxSpeed = maxSpeed;
        }
    
        public String getBrand() {
            return brand;
        }
    
        public void setBrand(String brand) {
            System.out.println("It is a " + brand + " Car");
            this.brand = brand;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            System.out.println("The price of this car " + price);
            this.price = price;
        }
    }
    

    在Spring配置文件中对Car进行属性注入的配置桥段

    <!--&&&&&&&&&&&&&&&&&&&&&&&&& setter属性方式注入 &&&&&&&&&&&&&&&&&&&&&& -->
    <bean id="car" class="com.vtstar.entity.Car">
         <property name="brand" value="保时捷 k3"/>
         <property name="maxSpeed" value="100"/>
         <property name="price" value="30.1"/>
    </bean>

    上面的代码配置的一个Bean,class属性对应前面建好的实体Car,<property/>标签对应Bean中的每一个属性,name为属性的名称,value为参数值,在Bean中拥有与其对应的Setter方法,maxSpeed对应setMaxSpeed(),price对应setPrice();

    运行一下 Tomcat,Spring容器会在Tomcat启动的时候创建;

    控制台输出的结果:


    二.构造函数注入

    构造函数注入是除属性注入外的另外一种注入方式,它保证了一些必要的属性在Bean实例化时就得到设置,确保在Bean实例化后就可以使用。

    值得一提的是构造函数注入又分为多种方式,我们慢慢来看。

    1. 按类型匹配入参

    如果任何可用的Car对象都需要使用到brand,maxSpeed,price的值,那使用Setter注入方式,则只能人为的在配置时提供保证而无法再语法上提供保证,那这个时候使用构造函数注入就能满足这一个要求,使用构造函数注入的前提是要保证Bean中有提供带参的构造函数。

         <!--1.根据参数类型注入-->
        <bean id="car1" class="com.vtstar.entity.Car">
            <constructor-arg type="int" value="300"/>
            <constructor-arg type="java.lang.String" value="红旗"/>
            <constructor-arg type="double" value="20000000.9"/>
        </bean>

    在<constructor/>元素中有一个type元素,它为Spring提供了判断配置项和构造函数入参对应关系的“信息”。

    控制台输出的结果:

    2. 按索引匹配入参

    Java语言通过入参的类型及顺序区分不同的重载方法。如果构造函数中有两个类型相同的入参,那么使用第一种方式是行不通的,因为type无法确认对应的关系。这时我们就需要使用索引匹配入参的方式来进行确认。

    为了更好的演示按索引匹配入参,将Car构造函数进行了修改

     public Car(String brand, String corp, double price) {
            System.out.println("brand :" + brand + " corp :" + corp + " price :"+price);
            this.brand = brand;
            this.corp = corp;
            this.price = price;
     }
        <!--2.通过入参位置下标-->
        <bean id="car2" class="com.vtstar.entity.Car">
            <constructor-arg index="0" value="400"/>
            <constructor-arg index="1" value="大众辉腾"/>
            <constructor-arg index="2" value="20000000"/>
        </bean>

    因为brand和corp都是String类型,所以Spring无法确定type为String的<constructor-arg/>到底对应的是brand还是corp。但是这种按索引匹配入参的方式能够消除这种不确定性

    控制台输出的结果:

    3. 联合使用类型和索引匹配入参

     

    有时需要Type和index联合使用才能确定配置项和构造函数入参的对应关系,举个栗子

        public Car(String brand, String corp, double price) {
            System.out.println("brand :" + brand + " corp :" + corp + " price :"+price);
            this.brand = brand;
            this.corp = corp;
            this.price = price;
        }
        public Car(String brand, String corp, int maxSpeed) {
            System.out.println("brand :" + brand + " corp :" + corp + " maxSpeed :"+maxSpeed);
            this.brand = brand;
            this.corp = corp;
            this.maxSpeed = maxSpeed;
        }

    在这里,Car拥有两个重载的构造函数,它们都有两个相同类型的入参,按照index的方式针对这样的情况又难以满足了这时就需要联合使用<constructor-arg/>中的type和index了。

        <!--3.通过参数类型和入参位置联合注入-->
        <bean id="car3" class="com.vtstar.entity.Car">
            <constructor-arg index="0" type="java.lang.String" value="30000000.0"/>
            <constructor-arg index="1" type="java.lang.String" value="卡迪拉克"/>
            <constructor-arg index="2" type="int" value="400"/>
        </bean>

    对于上图的代码清单如果只根据index来进行匹配入参,那么Spring无法确认第三个参数是price还是maxSpeed了,所以解决这种有歧义的冲突,请将type和index结合使用,对于因参数数目相同而类型不同引起的潜在配置歧义问题,Spring容器可以正确的启动且不会给出报错信息,他将随机采用一个匹配的构造函数实例化Bean,而被选择的构造函数可能并不是用户所期望的那个。因此,必须要特别谨慎,以避免潜在的错误。

    控制台输出的结果:

    4.通过自身类型反射入参

    如果Bean的构造函数入参类型是可辨别的,什么是可辨别的入参类型呢?(非基础数据类型且入参类型各异

    我们再建一个Boss实体类,在Boss类中引用Car类

    package com.vtstar.entity;
    
    import java.util.Date;
    
    /**
     * @ClassName Boss
     * @Description TODO
     * @Author XiaoWu
     * @Date 2018/9/6 11:22
     * @Version 1.0
     **/
    public class Boss {
        private String name;
        private Car car;
        private Integer age;
    
        public Boss() {
        }
    
        public Boss(String name, Car car,Integer age) {
            System.out.println("The name of the boss " + name + " ,He has a  " + car.getBrand()+" age is "+age);
            this.name = name;
            this.car = car;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public Car getCar() {
            return car;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    

    Spring配置Boss相关的Bean,由于name, car ,age入参都是可辨别的,所以无须在<constructor-arg/>中指定type和index。

        <!--4.通过自身类型反射入参-->
        <bean id="boss" class="com.vtstar.entity.Boss">
            <constructor-arg value="Tom"/>
            <constructor-arg ref="car1"/>
            <constructor-arg value="20"/>
        </bean>

    但是为了避免潜在配置歧义引起的张冠李戴的情况,如果Bean存在多个构造函数,那么显式指定index和type属性是一种良好的配置习惯。

    看控制台输出的结果:

     

    5.循环依赖问题

    Spring容器对构造函数配置Bean进行实例化有一个前提,即Bean构造函数入参引用的对象必须已经准备就绪。由于这个机制,如果两个Bean都相互引用,都采用构造函数注入方式,就会发生类似于线程死锁的循环依赖问题。

        <!--5.循环依赖注入-->
        <bean id="boss1" class="com.vtstar.entity.Boss">
            <constructor-arg index="0" value="Tom"/>
            <constructor-arg index="1" ref="car4"/>
            <constructor-arg index="2" value="20"/>
        </bean>
    
        <bean id="car4" class="com.vtstar.entity.Car">
            <constructor-arg index="0" value="232.9"/>
            <constructor-arg index="1" ref="boss1"/>
        </bean>

    控制台输出的结果:(这就是采用循环注入方式产生最大的问题)

    如何解决这种问题?将相互依赖的两个Bean中的其中一个Bean采用Setter注入的方式即可。

        
        <!--5.循环依赖注入-->
        <bean id="boss1" class="com.vtstar.entity.Boss">
            <constructor-arg index="0" value="Tom"/>
            <constructor-arg index="1" ref="car"/>
        </bean>
    
        <bean id="car" class="com.vtstar.entity.Car">
            <property name="brand" value="保时捷 k3"/>
            <property name="maxSpeed" value="100"/>
            <property name="price" value="30.1"/>
        </bean>

    控制台输出结果:

     


    构造函数注入方式:
    优点:
           1.构造函数可以保证一些重要的属性在bean实例化的时候就设置好,避免因为一些重要的属性没有提供而导致一个无用的Bean 实例情况
           2.不需要为每个属性提供Setter方法,减少了类的方法个数
           3.可以更好的封装类变量,不需要为每个属性提供Setter方法,避免外部错误的调用

    缺点:
          1.如果一个类属性太多,那么构造函数的参数将变成一个庞然大物,可读性较差
          2.灵活性不强,在有些属性是可选的情况下,如果通过构造函数注入,也需要为可选的参数提供一个null值
          3.如果有多个构造函数,则需要考虑配置文件和具体构造函数匹配歧义的问题,配置上相对复杂
          4.构造函数不利于类的继承和拓展,因为子类需要引用父类复杂的构造函数
          5.构造函数注入有时会造成循环依赖的问题

    三. 工厂注入

    既然需要一个工厂,那么我们需要创建一个CarFactory类

    package com.vtstar.ioc;
    
    import com.vtstar.entity.Car;
    
    /**
     * @ClassName CarFactory
     * @Description TODO
     * @Author XiaoWu
     * @Date 2018/9/6 13:55
     * @Version 1.0
     **/
    public class CarFactory {
        /*
         * @methodName createHongQiCar
         * @Description 创建红旗轿车制造工厂
         * @Date 2018/9/6 13:58
         * @Param []
         * @return com.vtstar.entity.Car
         **/
        public Car createHongQiCar(){
            Car car = new Car();
            car.setBrand("红旗H1");
            System.out.println("这里是非静态工厂的创建..." + car.getBrand());
            return car;
        }
    
        /*
         * @methodName createDaZhongCar
         * @Description 创建大众汽车制造工厂
         * @Date 2018/9/6 14:02
         * @Param []
         * @return com.vtstar.entity.Car
         **/
        public static Car createDaZhongCar(){
            Car car = new Car();
            car.setBrand("大众GoGoGo");
            System.out.println("这里是静态工厂的创建..." + car.getBrand());
            return car;
        }
    }
    

    工厂注入方式分为 静态工厂和非静态工厂,相关Spring配置如下:

        <!--非静态注入工厂方法-->
        <bean id="carFactory" class="com.vtstar.ioc.CarFactory"/>
        <bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar"/>
    
        <!--静态注入工厂方法-->
        <bean id="car6" class="com.vtstar.ioc.CarFactory" factory-method="createDaZhongCar"/>

    看控制台输出的结果:

     


    Spring 提供给了我们多种注入方式,需要使用哪种方式各位同鞋可以根据自身的场景下考量,

    这篇文章就分享到这啦,溜啦溜啦~~   

    展开全文
  • IOC与DI的讲解以及依赖注入三种方式

    千次阅读 多人点赞 2018-03-13 19:39:03
    spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入...
  • Spring依赖注入三种方式

    千次阅读 2021-10-26 21:10:16
    Spring的依赖注入,我们一般使用@Autowired注解来完成,关于依赖注入一般有三种方式: 变量注入、构造器注入、setter方法注入,下面我们仔细分析一下三种注入方式各自的特点以及使用场景。 一、变量注入(Field ...
  • 依赖注入(DI)的三种实现方式

    万次阅读 2017-09-21 10:28:24
    本文来探讨一下依赖注入三种实现方式是哪三种,Spring的支持又怎么样。 首先,依赖注入(DI)的实现方式三种:设值注入、构造方法注入、接口注入,下面来看看这三种注入方式在Spring中的支持怎么样。 1、设值...
  • Spring积累(3):依赖注入3种方式

    千次阅读 2021-08-08 16:12:08
    目录 一、依赖注入方式 Spring的依赖注入有3种方式: 1、使用属性注入 2、构造函数注入 使用方式: (1)按类型匹配入参 (2)按索引匹配入参 (3)联合使用类型和索引匹配入参 3、使用字段(Filed)注入(用于注解...
  • spring 依赖注入三种方式

    千次阅读 2020-12-07 12:46:01
    @Autowired:构造器,参数,...第一、set方式注入 //Car类 package com.spring.bean; @Component public class Car { public Car() { System.out.println("car...constructor"); } } //Boss类 package com.sp
  • php依赖注入三种方式

    千次阅读 2019-12-30 17:54:02
    控制反转(Inversion of Control,...下面我们就为大家介绍一下php依赖注入三种方式。 一、构造器注入  将被依赖对象通过构造函数的参数注入给依赖对象,并且在初始化对象的时候注入。 优点:  对象初始化完...
  • [Spring] IoC的理解及三种依赖注入方式Spring---IoC的理解及三种依赖注入方式IoC是什么意思依赖控制反转Spring提供的依赖注入三种方式setter注入(属性注入)构造器注入p命名空间注入(工厂方法注入)@Autowired ...
  • SpringBoot之三种常见的依赖注入方式

    千次阅读 2021-07-13 09:54:56
    总结 Spring中Autowired注入的两种方式: byType:默认是按照类型注入,与bean的属性具有相同类型的其他bean自动装配到bean 的对应属性中。 byName:与bean的属性具有相同名字的其他bean,自动装配到对应的属性中。...
  • Java依赖注入三种方式

    千次阅读 2019-09-10 09:33:46
    Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式主要有三种:构造方法注入,setter注入,基于注解的注入。 构造方法注入 通过Spring配置文件,标签 <constructor-arg ref="" private UserDao ...
  • Spring常用的三种依赖注入方式

    千次阅读 2020-01-22 18:34:54
    资料来源: 1、https://blog.csdn.net/a745233700/article/details/80959716... ... 1 问题由来 1、传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象,这种开发方式存在的问...
  • Spring依赖注入三种实现方式

    千次阅读 2020-03-27 06:57:58
    依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念。 当某个JAVA实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的实例(例如,使用 new 关键字获得被调用...
  • Spring 三种依赖注入方式.doc Spring 三种依赖注入方式.doc
  • Spring IOC(依赖注入三种方式)

    万次阅读 2018-07-09 16:38:51
    Spring IOC(依赖注入三种方式):1、Setter方法注入。2、构造方法注入。3、P命名空间注入。Spring IOC(依赖注入的五不同数据类型):1、注入直接量(基本数据类型、字符串)2、引用其他Bean组件。3、使用内部...
  • 依赖注入的两常用的注入方式

    千次阅读 2019-03-03 15:24:34
    在Spring框架中,主要有两种依赖注入方式:基于构造函数、基于setter方法 1.基于构造函数 基于构造函数的DI(依赖注入)是通过调用具有多个参数的的构造函数的额容器来完成的,每个参数表示依赖关系,下面演示一...
  • spring IOC中三种依赖注入方式

    千次阅读 2018-06-30 18:20:49
    spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控制什么?依赖注入...
  • AngularJS ng依赖注入三种方式

    千次阅读 2017-07-29 17:48:12
    一.ng的四注入方式 ...最基本的依赖注入方式 {{gameName}} //最基本的依赖注入方式 var MyModule = angular.module("MyModule",[]); MyModule.controller('MyCtrl',['$scope', function($scope){
  • Bean 的三种依赖注入方式介绍

    万次阅读 2018-08-20 16:17:46
    接下来将详细的向大家介绍Spring容器支持的三种依赖注入方式以及具体配置方法: • 属性注入方法 • 构造函数注入方法 • 工厂方法注入方法   一.属性注入 属性注入即通过setXXX()方法注入Bean的属性值...
  • Spring中的依赖注入三种方法 基于构造方法 setter注入(常用) 接口注入(不常用) Bean如下 package spring; public class Role { private Long id; private String roleName; private String n...
  • spring四种依赖注入方式

    万次阅读 2019-05-07 10:49:18
    平常的java开发中,程序员在某个类中需要依赖其它类的方法,通常是new一个依赖类再调用类...依赖注入的另一说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 391,057
精华内容 156,422
关键字:

依赖注入的三种方式

友情链接: Lecture-01 (1).zip