Spring基础——XML配置Bean的依赖注入

目录

  • 什么是依赖注入
    • 依赖的解析
  • Spring提供的两种注入方式
    • 1. 基于构造器的赖注入
      • 1.1 通过类型注入
      • 1.2 通过索引注入
      • 1.3 通过参数名注入
      • 1.4 通过静态工厂方法参数注入
    • 基于Setter的依赖注入
  • Spring对不同类型的注入方式
    • 1. 字面值(String,基本类型)注入
    • 2. 引用类型注入
    • 3. 集合类型注入
    • 4. 集合合并
    • 5. 内部Bean
  • Spring使用命名空间快捷注入
    • 使用p命名空间的XML
    • 使用c命名空间的XML
  • Spring使用dependes-on
  • 懒加载注入Bean
  • Spring自动注入
    • 自动注入的局限
    • 将Bean排除自动注入的搜索
  • Spring方法注入

什么是依赖注入

  • 依赖指的是对象要完成某种功能方法,需要其他对象或属性一起协作完成,而被需要的其他对象和属性则被称为对象的依赖
  • 依赖注入(DI)是Spring IoC技术实现的关键,其本质是Bean通过调用Class反射的构造函数或使用服务器定位模式来逆向控制依赖的实例化过程。(换句话说Spring使用了服务器定位模式来实现DI)
  • 使用DI技术可以让代码变的更加干净,(有的文章会说IoC完全消除了对象之间的依赖关系,实质上依赖关系是不会被消除的,DI只是让对象之间的依赖从类的内部绑定转变为从外部注入,从而降低代码的耦合度,完全消除的概念是指这两对象就没有任何联系了,互不干涉,也不存在调用),当对象被外部提供依赖时,我们不需要查询其依赖关系,也不需要去关注依赖对象的位置和类别,因此代码会更容易被维护和测试。

依赖的解析

  • 首先通过XML,Java代码或者注解来描述Bean的配置数据
    • 每个Bean的依赖通过属性,构造函数的参数,静态工厂方法参数(需要工厂方法设置的参数能代理正常的构造函数)的形式进行表达
    • 每个配置的属性和构造参数都要被赋予值或引用
    • 作为直接传递数值的属性或参数均以字符串的形式进行配置,在Spring中会自动转换成对应类型
  • 在Spring容器创建时,Spring ApplicationContext会验证每个Bean的配置,并将具有单例作用域的Bean实例化,其他Bean则会在被请求的时候才会被创建

Bean的循环依赖
在遇到BeanA引用BeanB,BeanB里又引用BeanA的时候,如果都通过构造参数进行互相注入,Spring容器会在运行时检测到这种循环引用并抛出异常。

对于Spring来说,Spring会在ApplicationContext加载配置时预先检测对还未被加载Bean的引用和循环依赖,到实际创建Bean的时候Spring会尽可能晚的设置属性和解析依赖关系(不能是构造注入,需要Setter注入),换句话说就是在有存在循环依赖的配置BeanA中,Spring检测到需要BeanB的依赖时,会在调用BeanA的setter方法之前实例化BeanB虽然Setter方法能解决循环依赖的问题,但是归根结底还是业务逻辑划分不清晰的缘故

Spring提供的两种注入方式

1. 基于构造器的赖注入

  • 构造器也被称为构造函数,既然DI是为了通过构造函数进行依赖注入,那么肯定是需要提供有参构造才能进行传参初始化。
  • Spring在进行构造注入的时候不需要明确指定调用哪个构造函数,Spring会根据传入的参数数量以及参数类型和名称自动匹配合适的构造方法
public class ConstructBeanImpl implements ConstructBean {

    private int count;
    private String poolName;
    private String poolPassword;
    private Double money;

    @Override
    public String toString() {
        return "ConstructBeanImpl{" +
                "count=" + count +
                ", poolName='" + poolName + '\'' +
                ", poolPassword='" + poolPassword + '\'' +
                ", money=" + money +
                '}';
    }

    public ConstructBeanImpl(int count, String poolName, String poolPassword, Double money) {
        this.count = count;
        this.poolName = poolName;
        this.poolPassword = poolPassword;
        this.money = money;
    }

    public ConstructBeanImpl(int count, String poolName, String poolPassword) {
        this.count = count;
        this.poolName = poolName;
        this.poolPassword = poolPassword;
    }

    public ConstructBeanImpl(int count, String poolName) {
        this.count = count;
        this.poolName = poolName;
    }

    @Override
    public void printHello() {
        System.out.println("construct hello world");

    }
}

1.1 通过类型注入

  • 在constructor-arg里配置type属性来通知Spring注入类型
 <!-- 基于构造器注入使用construct-arg标签进行标记 -->
 <!-- 注入的数据可以是通过type类型进行匹配,也可以是通过构造参数的序列进行注入 -->
 <!-- 请注意务必要确保有与注入属性数量相同的构造参数 -->
 <bean id="constructBean" class="com.nobugnolife.bean.impl.ConstructBeanImpl">
     <constructor-arg type="int" value="114"/>
     <constructor-arg type="java.lang.String" value="mysql.driver"/>
 </bean>

1.2 通过索引注入

  • 在constructor-arg里配置index来确定注入构造参数的位置,从左往右,下标从0开始
 <!-- 使用类型注入的构造注入方法在遇到参数类型相同的构造参数时容易出现歧义,可以通过按照索引的方式进行定位注入 -->
 <!-- 索引下标从0开始,从左往右的参数顺序 -->
 <bean id="constructBean01" class="com.nobugnolife.bean.impl.ConstructBeanImpl">
     <constructor-arg index="0" value="11145"/>
     <constructor-arg index="1" value="mysql.driver"/>
     <constructor-arg index="2" value="123321"/>
 </bean>

1.3 通过参数名注入

  • 在constructor-arg中通过name提供对应参数名
<!-- 如果遇到同类型,同等数量的构造参数的构造方法,还可以使用构造参数名来消除歧义 -->
<bean id="constructBean02" class="com.nobugnolife.bean.impl.ConstructBeanImpl">
    <constructor-arg name="count" value="114514"/>
    <constructor-arg name="poolName" value="mysql.driver"/>
    <constructor-arg name="poolPassword" value="123321"/>
    <constructor-arg name="money" value="10000.11111"/>
</bean>
  • 这里的参数名可以使用注解@ConstructorProperties来重命名构造参数
@ConstructorProperties({"count","name","password","money"})
public ConstructBeanImpl(int count, String poolName, String poolPassword, Double money) {
    this.count = count;
    this.poolName = poolName;
    this.poolPassword = poolPassword;
    this.money = money;
}
  • XML配置的为注解所标记的构造参数名
<bean id="constructBean02" class="com.nobugnolife.bean.impl.ConstructBeanImpl">
    <constructor-arg name="count" value="114514"/>
    <constructor-arg name="name" value="mysql.driver"/>
    <constructor-arg name="password" value="123321"/>
    <constructor-arg name="money" value="10000.11111"/>
</bean>

1.4 通过静态工厂方法参数注入

  • 上文提到过,如果静态工厂方法能代理构造函数返回对象实例的话,同样也可以使用静态工厂参数进行构造注入
  • 首先创建静态工厂类(实例工厂的方法以此类推即可
public class ConstructFactory {
    private ConstructFactory() {}
    public static ConstructBean createConstructBean(int count, String poolName, String poolPassword, Double money){
        return new ConstructBeanImpl(count,poolName,poolPassword,money);
    }
}
  • 然后将对应配置的class替换成静态工厂的类路径即可,还有添加factory-method
 <bean id="constructBean03" class="com.nobugnolife.factory.ConstructFactory" factory-method="createConstructBean">
     <constructor-arg name="count" value="114514"/>
     <constructor-arg name="poolName" value="mysql.driver"/>
     <constructor-arg name="poolPassword" value="14444"/>
     <constructor-arg name="money" value="1002.221"/>
 </bean>

基于Setter的依赖注入

  • 使用setter注入的话是Spring容器在调用无参构造实例化Bean之后调用setter方法进行注入,因此请确保类能正常调用无参构造。
  • 通过property标签实现Setter的依赖注入
 <bean id="setterBean" class="com.nobugnolife.bean.impl.SetterBeanImpl">
     <property name="beanOne" ref="beanOne"/>
     <property name="id" value="10"/>
     <property name="name" value="mybean"/>
 </bean>

Spring对不同类型的注入方式

1. 字面值(String,基本类型)注入

  • Spring对可以直接传值的属性统一使用value进行注入,并且均使用字符串形式注入(在Spring加载ApplicationContext的时候会自动将这些配置转化成对应属性的类型
  • 构造器和Setter均适用,这里就不分开举例了
<bean id="simpleTypeDao" class="com.nobugnolife.dao.impl.SimpleTypeDaoImpl">
    <!-- num对应在类里的int属性名num -->
    <property name="num" value="10"/>
    <!-- point对应float属性 -->
    <property name="point" value="1.1"/>
    <!-- flag对应boolean -->
    <property name="flag" value="true"/>
    <!-- bt对应byte -->
    <property name="bt" value="127"/>
    <!-- ch对应char -->
    <property name="ch" value="c"/>
    <!-- lg对应long -->
    <property name="lg" value="114514134"/>
    <!-- money对应double -->
    <property name="money" value="3.14159"/>
    <!-- str对应String -->
    <property name="str" value="hello world"/>
</bean>

2. 引用类型注入

  • 引用类型注入使用ref进行表述,可以是独立的ref标签,也可以是内部ref属性
<bean id="constructRefBean" class="com.nobugnolife.bean.impl.ConstructRefBeanImpl">
    <constructor-arg ref="beanOne"/>
    <constructor-arg>
        <ref bean="beanTwo"/>
    </constructor-arg>
</bean>
  • 在配置引用类型注入的时候如果传入的引用找不到id或者name的话则会返回空指针
  • 在Spring中,如果遇到具备重复配置信息或者是相似重复属性的配置Bean时,可以通过抽象出父Bean(可以是类继承的方式,或者是子Bean对应的类包含父Bean中所有的属性父Bean的配置只能是abstract或者是lazy-init,不能让工厂实例化Bean)来进行parent继承
  • Parent类
public class ParentBean {
    private String name;
    private String password;

    public void setName(String name) {
        this.name = name;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "ParentBean{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public String getPassword() {
        return password;
    }
}
  • 子类A通过继承的方式传递parent中的属性
public class SonBeanA extends ParentBean {
    private int connectNum;
    private int timeout;
    private int poolMax;

    public void setConnectNum(int connectNum) {
        this.connectNum = connectNum;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setPoolMax(int poolMax) {
        this.poolMax = poolMax;
    }

    @Override
    public String toString() {
        return "SonBean{" +
                "name=" + getName() +
                ", password" + getPassword() +
                ", connectNum=" + connectNum +
                ", timeout=" + timeout +
                ", poolMax=" + poolMax +
                '}';
    }
}
  • 子类B中包含parent中所有的属性
public class SonBeanB {
    //    private ParentBean parentBean;
    private String tools;

    private String password;

    @Override
    public String toString() {
        return "SonBeanB{" +
                "tools='" + tools + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                '}';
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private String name;

    public void setName(String name) {
        this.name = name;
    }


    public void setTools(String tools) {
        this.tools = tools;
    }

}
  • XML配置
<!-- 设置abstract为true后,容器将不会实例化Bean对象,但会保留配置属性 -->
<bean id="parentBean" abstract="true">
    <property name="name" value="msyql"/>
    <property name="password" value="123"/>
</bean>


<!-- 通过parent可以继承父bean的属性配置,同时也可以覆盖父bean的配置,子bean的类需要继承或包含父bean中所有的属性 -->
<bean id="sonBeanA" class="com.nobugnolife.bean.impl.SonBeanA" parent="parentBean">
    <property name="poolMax" value="100"/>
    <property name="timeout" value="1000"/>
    <property name="connectNum" value="30"/>
</bean>


<!-- spring提供的parent不只是可以通过继承,也可以是当前类所包含的属性,确保父Bean中有的属性,子Bean对应的类也有,注意是类,不是bean -->
<bean id="sonBeanB" class="com.nobugnolife.bean.impl.SonBeanB" parent="parentBean">
    <property name="tools" value="rock and stone"/>
    <!-- 同样也可以覆盖父bean中的属性,如果对应类而不是Bean是非继承关系的话,需要确保类中有相同的属性 -->
    <property name="name" value="MongoDB"/>
</bean>

在Spring Framework4.0之后ref就不再支持local属性,可以替换成ref bean

3. 集合类型注入

  • List注入
<!-- List注入 -->
<property name="idList">
    <list>
        <value>1</value>
        <value>2</value>
        <value>3</value>
    </list>
</property>
  • set注入
<!-- Set注入 -->
<property name="nameSet">
    <set>
        <value>xiaoming</value>
        <value>lisi</value>
        <!-- 在集合注入中同样可以使用引用注入,只要有配置的引用bean -->
        <idref bean="myString"/>
    </set>
</property>
  • property注入
<!-- property注入 -->
<property name="properties">
    <props>
        <prop key="adminstrator">admin@go.org</prop>
        <prop key="password">admin</prop>
        <prop key="phone">114514</prop>
    </props>
</property>
  • map注入
<!-- map注入 -->
<property name="map">
    <map>
        <entry key="1" value-ref="beanOne01"/>
        <entry key="2" value-ref="beanOne02"/>
    </map>
</property>
  • Spring会通过集合中定义的泛型类型,自动将字符串转化为对应类型的数值如:
 private Map<String, Float> accounts;
<property name="accounts">
    <map>
        <entry key="one" value="9.99"/>
        <entry key="two" value="2.75"/>
        <entry key="six" value="3.99"/>
    </map>
</property>
  • 如果value设定为""空字符串,则默认数值为空或者Null

4. 集合合并

  • Spring支持让子集合(list,map,set,props)元素继承父集合的值,并且子集合的元素能覆盖父集合中的值。
  • 如果不知道什么是Bean继承的话可以参考Bean定义的继承
  • 父集合
<bean id="parentBean03" abstract="true">
    <property name="props">
        <props>
            <prop key="username">
                administrator
            </prop>
            <prop key="password">admin</prop>
        </props>
    </property>
</bean>
  • 子集合
<bean id="childBean" class="com.nobugnolife.bean.impl.ChildBean" parent="parentBean03">
    <property name="props">
        <!-- 子集合重写密码并新增email配置 -->
        <props>
            <prop key="password">123</prop>
            <prop key="email">example@gmail.com</prop>
        </props>
    </property>
</bean>

list,map,set等用法基本和上述结构差不多,不过对于有序集合List,父列表的值会被排在子列表的值前面。
并且集合合并只能对同类型的集合合并,无法混合不同类型集合进行合并

5. 内部Bean

  • 当某个类只是作为当前类的属性而并没有其他引用的时候,可以通过创建内部Bean的方式进行注入,这样就不需要配置新的Bean,内部Bean不需要定义ID和Name,并且也会忽略创建的作用域
  • 内部Bean
public class InnerBean {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "InnerBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
  • 需要内部bean的类
public class HumanBeanImpl implements HumanBean {
    @Override
    public void printHello() {
        System.out.println("human hello world");
    }

    private InnerBean innerBean;

    @Override
    public String toString() {
        return "HumanBeanImpl{" +
                "innerBean=" + innerBean +
                '}';
    }

    public void setInnerBean(InnerBean innerBean) {
        this.innerBean = innerBean;
    }
}

  • 配置xml
<bean id="humanBean" class="com.nobugnolife.bean.impl.HumanBeanImpl">
    <property name="innerBean">
        <bean class="com.nobugnolife.bean.impl.InnerBean">
            <property name="name" value="Sham"/>
            <property name="age" value="28"/>
        </bean>
    </property>
</bean>

Spring使用命名空间快捷注入

使用p命名空间的XML

  • p-namespace可以简化bean中property元素来配置Bean属性注入
  • p命命名空间是Spring基于XML Schema定义的可扩展配置格式的命名空间,因此需要先导入p命名空间配置
xmlns:p="http://www.springframework.org/schema/p"
  • 使用p命名空间只需要在bean的属性前添加p:即可,对引用类型的配置属性需在属性后加-ref
<!-- 使用p命名空间对bean进行setter注入,对于引用类型需在属性名后加-ref -->
<bean id="setterBean02" class="com.nobugnolife.bean.impl.SetterBeanImpl"
      p:beanOne-ref="beanOne"
      p:id="11"
      p:name="pBean"/>

p命名空间不像标准的XML格式那样灵活。例如,声明属性引用的格式与以 Ref 结尾的属性发生冲突,而标准的XML格式则不会

使用c命名空间的XML

  • 与p命名空间相似,c命名空间是对构造注入的constructor-arg标签进行的简化
  • 首先导入c命名空间
xmlns:c="http://www.springframework.org/schema/c"
  • 通过参数名进行c命名空间的构造注入
<!-- 利用c命名空间进行构造注入 -->
<bean id="constructBean04" class="com.nobugnolife.bean.impl.ConstructBeanImpl"
      c:count="12"
      c:money="22.3"
      c:poolName="mysql"
      c:poolPassword="123321"/>
  • c命名空间通过索引形式进行的构造注入,引用类型的注入方式与p命名空间一样
<!-- c命名空间通过序列索引形式的构造注入 -->
<bean id="constructBean05" class="com.nobugnolife.bean.impl.ConstructRefBeanImpl"
      c:_0-ref="beanOne"
      c:_1-ref="beanTwo"/>

Spring使用dependes-on

  • 对于Bean的直接依赖来说,可以通过配置属性中的ref进行引用,而对于一个类在初始化之前需要先初始化类中的静态变量时,可以使用depends-on属性来指定Bean之间的初始化时间依赖关系。
public class ManagerBean {
    private String driver;
    private String url;
    private String userName;
    private String password;

    public ManagerBean() {
        System.out.println("manager bean以被实例化");
    }

    public String getDriver() {
        return driver;
    }

    public String getUrl() {
        return url;
    }

    public String getUserName() {
        return userName;
    }

    public String getPassword() {
        return password;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    @Override
    public String toString() {
        return "ManagerBean{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

  • 依赖ManagerBean的DependBean
public class DependBeanImpl implements DependBean {
    private ManagerBean manager;

    public DependBeanImpl() {
        System.out.println("depend bean已被实例化");
    }

    public void setManager(ManagerBean manager) {
        this.manager = manager;
    }

    @Override
    public void printHello() {
        System.out.println("depend bean hello world");
    }

    @Override
    public void registDataSourct() {
        System.out.println("创建数据库连接对象:" +
                "数据库驱动:" + manager.getDriver() +
                "\n数据库连接地址: " + manager.getUrl() +
                "\n连接用户名:" + manager.getUserName() +
                "\n连接密码:" + manager.getPassword());
    }
}
  • XML配置dependes-on,如果有多个依赖,使用逗号,空格或分号在字符串中进行分割即可
<bean id="dependBean" class="com.nobugnolife.bean.impl.DependBeanImpl" depends-on="managerBean">
    <property name="manager" ref="managerBean"/>
</bean>

<bean id="managerBean" class="com.nobugnolife.bean.impl.ManagerBean">
    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306"/>
    <property name="userName" value="root"/>
    <property name="password" value="123"/>
</bean>

depends-on

  • 如果不配置depends-on的话,depend bean会在manager bean之前被实例化,这样是不符合逻辑的
    depends-off
    depends-on可以指定Bean的初始化时间以来关系,而在单例模式的Bean中,也可以指定小伙时间的依赖关系,在Bean中如过定义了depends-on的依赖,则依赖的Bean会在本体被销毁前销毁

懒加载注入Bean

  • 在默认的单例模式Bean中Spring容器加载ApplicationContext的时候会非常急切的创建和配置所有的单例模式Bean(这样会尽可能早的发现环境中的错误,而不是等到被调用的时候再报错),如果不想要Bean立即被创建,可以使用懒加载模式阻止Bean的实例化,懒加载模式下的Bean只有当在第一次被请求创建的时候才会实例化对象,而不是在启动容器的时候。
  • Bean属性中配置lazy-init=true即可开启懒加载
<bean id="lazyBean" class="com.nobugnolife.bean.impl.LazyBean" lazy-init="true"/>
<bean id="activeBean" class="com.nobugnolife.bean.impl.ActiveBean"/>
  • 测试是否在被加载时调用,优先实例化lazyBean,然后再在activeBean后调用lazyBean的方法,如果不是懒加载,那么activeBean的创建会和lazyBean的方法挨在一起
@Test
public void testDependBean() throws Exception {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("dependBean.xml");
    DependBean dependBean = ctx.getBean(DependBean.class);
    dependBean.registDataSourct();
    System.out.println(dependBean);
}

lazy-init

Spring自动注入

  • Spring容器可以自动建立与依赖Bean之间的联系,可以省去手动配置属性或构造参数的过程。自动注入可以极大减少对指定属性或构造参数的配置,可以随着对象的变化而更新配置,因此在开发过程中,自动注入是主流用法,能极大提升开发效率。
  • Spring基于XML的自动注入通过在bean标签的属性中autowire属性来定义,自动注入的形式一共有4种
模式说明
no默认关闭自动注入模式
byName通过属性名称进行自动注入,Spring会自动匹配一个与需要自动注入属性同名的bean
byType通过属性类型注入,如果容器中只有一个与当前被注入类的类型相同或者为其配置的实现类的类型,则会进行自动注入,
如果存在多个会报错,如果没有匹配的Bean则不会发生任何事
constructor通过被注入Bean的构造器参数类型查找同类型或配置的实现类型的Bean进行注入,与byType类似
<!-- 创建需要注入依赖的Bean -->
<bean id="bean" class="com.nobugnolife.bean.impl.BeanImpl">
</bean>

<!-- 通过命名自动注入bean,Spring容器会在Bean中查询与autoWire中属性bean命名相同的Bean对象 -->
<bean id="autoWireBean" class="com.nobugnolife.bean.impl.AutoWireBeanImpl" autowire="byName"/>

<!-- 通过属性类型进行注入,Spring会自动在容器中查询与属性类型相匹配的配置Bean -->
<bean id="autoWireBean02" class="com.nobugnolife.bean.impl.AutoWireBeanImpl" autowire="byType"/>

<!-- 通过构造参数类型进行自动注入,Spring会自动在容器中查询符合类提供的构造器参数的类型相匹配的Bean,最好提供全参数构造 -->
<bean id="autoWireBean03" class="com.nobugnolife.bean.impl.AutoWireBeanImpl" autowire="constructor"/>
  • 注意使用construct注入的话要提供全参构造否则会报错
public class AutoWireBeanImpl implements AutoWireBean {
    private Bean bean;

    @Override
    public String toString() {
        return "AutoWireBeanImpl{" +
                "bean=" + bean +
                '}';
    }

    public AutoWireBeanImpl() {
    }

    public AutoWireBeanImpl(Bean bean) {
        this.bean = bean;
    }

    public void setBean(Bean bean) {
        this.bean = bean;
    }

    @Override
    public void printHello() {
        bean.printHello();
        System.out.println("autowire bean hello world");
    }
}

自动注入的局限

  • 自动注入的优先级是在setter与构造器注入之后,因此如果存在构造注入或setter注入,那么自动注入的效果会被覆盖
  • 自动注入无法注入简单的属性,如基本数据类型和String
  • 自动注入的效果不一定准确,虽然Spring在尽可能的避免对模糊情况下的猜测,但总可能会发生意外
  • 自动注入如果在项目中统一被使用,效果会很好,但如果大量使用配置的情况下混合使用自动注入则会带来误解。

将Bean排除自动注入的搜索

  • 在bean标签中通过设置autowire-candidate=false属性可以将当前Bean排除自动注入的搜索。

Spring方法注入

  • 正在修建中。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/430956.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

“而且,再加上”可以用哪个语法来表示,柯桥考级韩语学习

语法 --는/은/ㄴ 데다가 1.语法&#xff1a;는/은/ㄴ 데다가 2.表示&#xff1a;用于谓词词干和体词谓词形后, 表示在原有的状况上再加上其他情况。 3.添加&#xff1a; 4.例句&#xff1a; 当然&#xff0c;与这个语法含义相近的还有不少语法&#xff0c;有一部分是初级暂时…

网络安全: Kali Linux 使用 hping3 阻塞目标主机

目录 一、实验 1.环境 2. 物理机测试远程连接 Windows server 3.Kali Linux 使⽤ hping3 ⼯具 二、问题 1. 常见的 DoS ⽅式有哪些 2.hping3 测试⼯具的命令格式和选项参数 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本IP备注Kali Linux2024.…

洗地机怎么选?2024年洗地机推荐,希亦、添可、追觅、石头哪一款清洁力更好?

洗地机是一款可以一遍搞定扫地和拖地一系列动作的清洁神奇&#xff0c;它能让我们真实的感受到打扫屋子是一件很减压的事情&#xff0c;但是目前市面上的洗地机太多了&#xff0c;大家都不知道怎么样的才算好&#xff0c;希亦、添可、追觅、石头洗地机值不值得买&#xff1f;我…

用边缘计算网关解决离散行业数采问题-天拓四方

一、引言 随着工业4.0时代的来临&#xff0c;离散制造行业正面临数字化转型的关键节点。离散制造的特点是小批量、多品种、高复杂度&#xff0c;如何实现高效、精准的数据采集与分析&#xff0c;提升生产效率和产品质量&#xff0c;成为行业亟待解决的问题。边缘计算网关作为一…

python数据类型及转换

一、数据类型 数据类型分为数值型、布尔型、字符串型等 1.1数值类型 数值类型可以分为整数类型、浮点数类型、复数类型 1.1.1整数类型 (1)概念&#xff1a;整数类型指数值是没有小数部分的&#xff0c;包含正整数、负整数和0 (2)进制种类&#xff1a;十进制--->234、5…

Lichee Pi 4A:RISC-V架构的开源硬件之旅

一、简介 Lichee Pi 4A是一款基于RISC-V指令集的强大Linux开发板&#xff0c;它凭借出色的性能和丰富的接口&#xff0c;吸引了众多开发者和爱好者的关注。这款开发板不仅适用于学习和研究RISC-V架构&#xff0c;还可以作为软路由、小型服务器或物联网设备的核心组件。 目录 一…

【pyinstaller打包记录】Linux系统打包可执行文件后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件&#xff08;可执行程序&#xff09;的工具。它能够将 Python 代码和其相关的依赖项&#xff08;包括 Python 解释器、依赖的模块、库文件等&#xff09;打包成一个独立的可执行文件&#xff0c;方便在不同环境中运行…

tomcat安装及jdk安装

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;属于轻量级应用服务器&#xff0c;在中小型系统和并发访问用户不是很多的场合下被普遍使用&#xff0c;是开发和调试JSP 程序的首选。对于一个初学者来说&#xff0c;可以这样认为&#xff0c;当在一台机器上配…

Android 拍照本地图片选择框架适配

前言 通常技术方案的选择、会带来后续一些不可控的东西&#xff0c;这也是没法避免的&#xff0c;程序开发者中同时面对、测试、领导、产品各种要求。同时在网络上查找的资料也只是很旧的&#xff0c;不一定适合新设备&#xff0c;需要推倒重新弄 1、解决方案通过意图选择器做…

Git 远程仓库之Github

目前我们使用到的 Git 命令都是在本地执行&#xff0c;如果你想通过 Git 分享你的代码或者与其他开发人员合作。 你就需要将数据放到一台其他开发人员能够连接的服务器上。 目前最出名的代码托管平台是Github&#xff0c;我们将使用了 Github 作为远程仓库。 添加远程库 要添…

C#与VisionPro联合开发——单例模式

单例模式 单例模式是一种设计模式&#xff0c;用于确保类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。单例模式通常用于需要全局访问一个共享资源或状态的情况&#xff0c;以避免多个实例引入不必要的复杂性或资源浪费。 Form1 的代码展示 using System; usi…

关于V5版本的echarts的引导线标签文字存在描边问题

1.如果存在描边&#xff1a;&#xff08;如图所示&#xff0c;炒鸡难受好吧&#xff0c;也不知道官方为什么这样初始化&#xff09; 2.只需在series的label中配置color:#FFF即可

ES入门二:文档的基本操作

索引管理 创建索引 删除索引 文档管理 创建文档 如果有更新需求&#xff0c;使用第一种如果有唯一性校验&#xff0c;使用第二种如果需要系统给你创建文档Id&#xff0c;使用第三种 &#xff08;这个性能更好&#xff09; 相比第一种&#xff0c;第三种的写入效率更高&#xf…

2.00001《Postgresql内幕探索》走读 之 查询优化

文章目录 1.1 概述1.1.1 Parser1.1.2 分析仪/分析器1.1.3 Rewriter1.1.4 Planner和Executer 1.2 单表查询的成本估算1.2.1 顺序扫描1.2.2 索引扫描1.2.3 排序 1.3 .创建单表查询的计划树1.3.1 预处理1.3.2 获取最便宜的访问路径示例1示例二 1.3.3 创建计划树示例1例二 1.4 EXEC…

appium2的一些配置

appium-desktop不再维护之后&#xff0c;需要使用appium2。 1、安装appium2 命令行输入npm i -g appium。安装之后输入appium或者appium-server即可启动appium 2、安装安卓/ios的驱动 安卓&#xff1a;appium driver install uiautomator2 iOS&#xff1a;appium driver i…

《汇编语言》 第3版 (王爽)实验6解析

第7章 实验6解析 &#xff08;1&#xff09;.编程&#xff0c;完成问题7.9中的程序。 问题7.9 编程&#xff0c;将datasg段中每个单词的前4个字母改为大写字母。 assume cs:codesg,ss:stacksg,ds:datasgstacksg segment ;开辟了栈段空间&#xff0c;容量为16个字节dw 0,0,0,0…

基于java springboot+redis网上水果超市商城设计和实现以及文档

基于java springbootredis网上水果超市商城设计和实现以及文档 博主介绍&#xff1a;多年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留…

Oracle 如何将txt文件中的数据导入数据库

使用文本导入器&#xff0c;可以将ASCII文件导入数据库。支持大多数面向行的格式&#xff0c;如逗号和制表符分隔的字段。导入程序将尝试自动确定文件格式&#xff0c;因此大多数时候您不会抰 需要定义任何内容&#xff0c;只需选择文件&#xff0c;选择一个表&#xff0c;然后…

爬虫案例二

第一步电影天堂_免费在线观看_迅雷电影下载_电影天堂网 (dytt28.com)电影天堂_电影下载_高清首发 (dytt89.com)电影天堂_免费在线观看_迅雷电影下载_电影天堂网 (dytt28.com) 打开这个网站 我直接打开 requests.exceptions.SSLError: HTTPSConnectionPool(hostwww.dytt28.com…

聚观早报 | 2024款腾势D9将发布;岚图汽车2月销量

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 3月2日消息 2024款腾势D9将发布 岚图汽车2月销量 苹果Vision Pro防汗新专利 真我12 Pro正式开售 Redmi K70/Pro…