spring自动装配bean入门教程

360 阅读2分钟

这是我参与更文挑战的第 11 天,活动详情查看

Spring 中自动装配 autowire 机制是指,由 Spring Ioc 容器负责把所需要的 bean,自动查找和赋值到当前在创建 bean 的属性中,无需手动设置 bean 的属性。

1、基于 xml 配置 bean 的装配方式:

  • no:默认的方式是不进行自动装配的,需要通过手工设置 ref 属性来进行装配 bean。
  • byName:通过 bean 的名称进行自动装配,如果一个 bean 的 property 与另一 bean 的 name 相同,就进行自动装配。
  • byType:通过参数的数据类型进行自动装配。
  • constructor:通过构造函数进行装配,并且构造函数的参数通过 byType 进行装配。
  • autodetect:自动探测,如果有构造方法,通过 construct 的方式自动装配,否则使用 byType 的方式自动装配。( 已弃用)

方式的定义在 AutowireCapableBeanFactory.AUTOWIRE_NO
AUTOWIRE_BY_NAME
AUTOWIRE_BY_TYPE
AUTOWIRE_CONSTRUCTOR
AUTOWIRE_AUTODETECT

2、基于注解完成 bean 的装配

  • @Autowired、@Resource、@Inject 都可以实现 bean 的注入@Autowired 是 Spring 推出的,功能最为强大,可以作用于 构造方法、setter 方法、参数、成员变量、注解(用于自定义扩展注解)@Resource 是 JSR-250 的规范推出@Inject 是 JSR-330 的规范推出
  • @Value 可以注入配置信息 @Autowired、@Inject、@Value 的解析工作是在 AutowiredAnnotationBeanPostProcessor 内,如何源码 1

@Resource 的解析工作是在 CommonAnnotationBeanPostProcessor 内,如何源码 2

源码 1public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

源码 2static {
    ...
    resourceAnnotationTypes.add(Resource.class);
    ...
}

基于 xml 的代码示例

1、no 方式

spring 配置文件,使用 ref 参数注入 bean,必须要有对象的 setter 方法,这里即 Person 的 setFr 方法。

没有 因没有注入 fr 属性,会报空指针错误。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
    <bean id="person" class="constxiong.interview.assemble.Person" autowire="no">
        <property name="fr" ref="fr"></property>
    </bean>
    <bean id="fr" class="constxiong.interview.assemble.FishingRod"></bean>
        
</beans>

鱼竿 bean

package constxiong.interview.assemble;
 
 
/**
 * 鱼竿
 * @author ConstXiong
 * @date 2019-07-17 09:53:15
 */
public class FishingRod {
 
    /**
     * 被使用
     */
    public void used() {
        System.out.println("钓鱼...");
    }
}

人 bean

package constxiong.interview.assemble;
 
 
/**
 * 人
 * @author ConstXiong
 * @date 2019-07-17 09:54:56
 */
public class Person {
 
    private FishingRod fr;
    
    /**
     * 钓鱼
     */
    public void fish() {
        fr.used();
    }
    
    public void setFr(FishingRod fr) {
        this.fr = fr;
    }
    
}

测试代码

package constxiong.interview.assemble;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class AssembleTest {
 
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring_assemble.xml");
        Person person = (Person)context.getBean("person");
        person.fish();
    }
    
}

2、byName 也是需要相应的 setter 方法才能注入

修改 spring 配置文件 autowire="byName"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
    <bean id="person" class="constxiong.interview.assemble.Person" autowire="byName"></bean>
    <bean id="fr" class="constxiong.interview.assemble.FishingRod"></bean>
        
</beans>

3、byType 也是需要相应的 setter 方法才能注入

修改 spring 配置文件 autowire="byType"

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
    <bean id="person" class="constxiong.interview.assemble.Person" autowire="byType"></bean>
    <bean id="fr" class="constxiong.interview.assemble.FishingRod"></bean>
        
</beans>

其他不变

4、constructor 无需 setter 方法,需要通过 构造方法注入 bean

修改 spring 配置文件 autowire="byType"

Person 类去除 setFr 方法,添加构造方法设置 fr 属性

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
    <bean id="person" class="constxiong.interview.assemble.Person" autowire="constructor"></bean>
    <bean id="fr" class="constxiong.interview.assemble.FishingRod"></bean>
        
</beans>
package constxiong.interview.assemble;
 
 
/**
 * 人
 * @author ConstXiong
 * @date 2019-07-17 09:54:56
 */
public class Person {
 
    private FishingRod fr;
    
    public Person(FishingRod fr) {
        this.fr = fr;
    }
    
    /**
     * 钓鱼
     */
    public void fish() {
        fr.used();
    }
    
}

1、2、3、4 的测试结果一致,打印

钓鱼...