当前位置: 首页 > 工具软件 > Autowire > 使用案例 >

spring autowire在xml中的使用

宫子晋
2023-12-01

1:说明

spring为了方便我们完成bean注入相关的配置工作,提供了自动注入功能,我们只需要按照其规则来进行配置,就能够让spring注入我们需要的bean了。

2:准备测试类

2.1:State

public class State {

	private String stateName;
	...snip...
}

2.2:Country

public class Country {

	// generate setters...
	private State state; // secondary type

	public void setState(State state) {
		this.state = state;
	}

	// print injected value on the console log
	public void display() {
		System.out.println("State name is: " + state.getStateName());
	}
}

3:autowire->no

这也是默认的自动注入的方式,即不使用自动注入,这种方式需要我们显示的在配置文件中通过<property>标签然后通过ref属性来设置,这也是默认的自动注入方式。

3.1:配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="no">
        <property name="state" ref="state"/>
    </bean>
</beans>

3.2:测试

@Test
public void test_autowire_no() {
    ClassPathXmlApplicationContext ac
            = new ClassPathXmlApplicationContext("autowiretest/test-autowire-no.xml");
    System.out.println(ac.getBean("country", Country.class).getState());
}

运行:

yudaosourcecode.autowiretest.State@42607a4f

Process finished with exit code 0

4:autowire->byType

这种方式是通过属性的类型,来进行自动注入。

4.1:配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="byType">
    </bean>
</beans>

可以看到此时就不需要通过<property>标签来配置了。

4.2:测试

@Test
public void test_autowire_bytype() {
    ClassPathXmlApplicationContext ac
            = new ClassPathXmlApplicationContext("autowiretest/test_autowire_bytype.xml");
    System.out.println("autowire byType: ");
    System.out.println(ac.getBean("country", Country.class).getState());
}

运行:

autowire byType: 
yudaosourcecode.autowiretest.State@646007f4

Process finished with exit code 0

但是当相同类型的bean有多个的时候byType的方式就不适用了,因为无法确定到底注入哪个bean,例如修改配置文件为如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State"/>
    <bean id="state1" class="yudaosourcecode.autowiretest.State"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="byType"/>
</beans>

再次运行程序:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating 
bean with name 'country' defined in class path resource 
[autowiretest/test_autowire_bytype.xml]: 
Unsatisfied dependency expressed through bean property 'state'; nested exception is 
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying 
bean of type 'yudaosourcecode.autowiretest.State' available: 
expected single matching bean but found 2: state,state1

出现这个异常的原因就是,相同类型的bean有两个,无法确定是哪个,即候选者bean有多个,为了解决这个问题,spring提供了autowire-candidate属性,代表在自动注入时是否作为候选bean,默认值是true,这里我们可以将其中一个设置为false,修改配置文件为如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State"/>
    <bean id="state1" class="yudaosourcecode.autowiretest.State" autowire-candidate="false"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="byType"/>
</beans>

再次运行程序,就可以正常完成注入了:

autowire byType: 
yudaosourcecode.autowiretest.State@646007f4

Process finished with exit code 0

不使用autowire-candidate的话也可以使用primary来指定首选bean,即设置一个优先级最高的bean作为目标,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State" primary="true"/>
    <bean id="state1" class="yudaosourcecode.autowiretest.State"/>
    <bean id="anotherState"
          class="yudaosourcecode.autowiretest.AnotherState"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="byType"
          lazy-init="true"/>
</beans>

5:autowire->byName

这种是通过属性的名称来作为目标bean的名称来完成自动注入,因为是通过名称,而spring的bean名称是不允许重复的,因此这种情况下相同类型的bean有多个,是不会有任何问题的。

5.1:配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State"/>
    <bean id="state1" class="yudaosourcecode.autowiretest.State"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="byName"/>
</beans>

5.2:测试

@Test
public void test_autowire_byname() {
    ClassPathXmlApplicationContext ac
            = new ClassPathXmlApplicationContext("autowiretest/test_autowire_byname.xml");
    System.out.println("autowiretest/autowire byname: ");
    System.out.println(ac.getBean("country", Country.class).getState());
}

运行:

autowiretest/autowire byname: 
yudaosourcecode.autowiretest.State@43a0cee9

Process finished with exit code 0

6:autowire->constructor

byTypebyName都是自动完成属性的注入,这里的constructor是自动完成构造函数的自动注入。

6.1:改造Country

定义一个构造函数使用state作为参数。

public class Country {

	private State state; // secondary type

	public Country(State state) {
		this.state = state;
	}

	// print injected value on the console log
	public void display() {
		System.out.println("State name is: " + state.getStateName());
	}
}

6.2:配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="state" class="yudaosourcecode.autowiretest.State"/>

    <bean id="country"
          class="yudaosourcecode.autowiretest.Country"
          autowire="constructor"/>
</beans>

6.3:测试

@Test
public void test_autowire_constructor() {
    ClassPathXmlApplicationContext ac
            = new ClassPathXmlApplicationContext("autowiretest/test_autowire_constructor.xml");
    System.out.println("by constructor: ");
    System.out.println(ac.getBean("country"));
}

6.4:需要注意的问题

构造函数的自动注入,在寻找目标bean的时候,默认使用的是byType,因此当目标bean有多个时候,同样会出现异常,此时也是可以通过autowire-candidate属性来解决,这里不再演示了,和4:autowire->byType中的情况是一致的。

7:总结

各种类型说明如下表:

autowire类型注入方式注入目标
no不自持自动注入,需要通过标签
<property>或者<constructor>配置
依配置决定
byType根据类型注入bean属性
byName根据名称注入bean属性
constructor根据类型注入构造函数参数
 类似资料: