spring装配bean的三种机制总结

创建应用对象之间协作关系的行为通常称为装配( wiring ),这也是依赖注入( DI )的本质。

配置 Spring 容器最常见的有三种方法

1. 在 XML 中进行显式配置;
2. 在 Java 中进行显式配置;
3. 隐式的 bean 发现机制和自动装配;

Spring 从两个角度来实现自动化装配:

  • 组件扫描( component scanning ): Spring 会自动发现应用上下文中所创建的 bean 。
  • 自动装配( autowiring ): Spring 自动满足 bean 之间的依赖。
    组件扫描和自动装配组合在一起就能发挥出强大的威力,它们能够将你的显式配置降低到最少。

自动化装配bean的方式:

首先构建一个spring的java工程:
写一个实体类:

package main.java.sia.knights.config.testDI;
import org.springframework.stereotype.Component;
@Component
public class Student {
    public void study(){
        System.out.println ("学生学习中。。。。");
    }
}

你需要注意的就是 Student 类上使用了 @Component 注解。这个简单的注解表明该类会作为组件类,并告知 Spring 要为这个类创建 bean 。没有必要显式配置 bean,因为这个类使用了 @Component 注解,所以 Spring 会为你把事情处理妥当。
不过,组件扫描默认是不启用的。我们还需要显式配置一下 Spring ,从而命令它去寻找带有 @Component 注解的类,并为其创建 bean 。下面的配置类展现了完成这项任务的最简洁配置:

package main.java.sia.knights.config.testDI;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class ConfigScan {
}

这上面有两个注解,

  • @Configuration

从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

  • @ComponentScan

ConfigScan 类并没有显式地声明任何 bean ,只不过它使用了 @ComponentScan 注解,这个注解能够在 Spring 中启用组
件扫描。
如果没有其他配置的话, @ComponentScan 默认会扫描与配置类相同的包。因为 ConfigScan 类位于 testDI包中,因此 Spring将会扫描这个包以及这个包下的所有子包,查找带有 @Component 注解的类。这样的话,就能发现 Student ,并且会在 Spring 中自动为其创建一个 bean 。
下面进行测试:

package main.java.sia.knights.config.testDI;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ConfigScan.class)
public class TestDI {

    @Autowired
    public Student Student;
    
    @Test
    public void testDi(){
        Student.study ();
    }
}

TestDI 使用了 Spring 的 SpringJUnit4ClassRunner ,以便在测试开始的时候自动创建 Spring 的应用上下文。注
解 @ContextConfiguration 会告诉它需要在 CDPlayerConfig 中加载配置。因为 CDPlayerConfig 类中包含了 @ComponentScan ,
因此最终的应用上下文中应该包含 Student 的bean。
使用 @Autowired能够从spring中获取Student 的bean,并将其注入到测试代码中,看下测试结果:
在这里插入图片描述
测试结果显示我们已经将student这个类交给spring管理,并使用到了它。

下面补充小知识:

为组件扫描的 bean 命名

Spring 应用上下文中所有的 bean 都会给定一个 ID 。在前面的例子中,尽管我们没有明确地为 Student设置 ID ,但 Spring 会根据类名为其指定一个 ID 。具体来讲,这个 bean 所给定的 ID 为 student,也就是将类名的第一个字母变为小写。如果想为这个 bean 设置不同的 ID ,你所要做的就是将期望的 ID 作为值传递给 @Component 注解。如下面代码所示:

@Component("teacher")
public class Student {
    public void study(){
        System.out.println ("学生学习中。。。。");
    }
}

还有另外一种为 bean 命名的方式,这种方式不使用 @Component 注解,而是使用 Java 依赖注入规范( Java Dependency Injection )中所提供的 @Named 注解来为 bean 设置 ID :

package main.java.sia.knights.config.testDI;
import javax.inject.Named;

@Named("teacher")
public class Student {
    public void study(){
        System.out.println ("学生学习中。。。。");
    }
}

这里你需要导入jar包javax.inject-1.jar,不然spring是找不到的,这种方式spring也是可以进行DI的;

通过 XML 启用组件扫描

在这里插入图片描述创建一个xml文件,用于启用注解扫描,文件内容:

<?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">

    <context:component-scan base-package="main.java.sia.knights.config.testDI"></context:component-scan>
</beans>

然后写一个配置类导入xml:

package main.java.sia.knights.config.testDI;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ImportResource("classpath:main/java/sia/knights/config/testDI/spring.xml")
public class ScanConfig {
}

最后进行单元测试:

package main.java.sia.knights.config.testDI;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ScanConfig.class)
public class TestDI2 {

    @Autowired
    public Student Student;

    @Test
    public void testDi(){
        Student.study ();
    }
}

同样,也能得到相同的结果。

通过xml注入bean

将上面的spring.xml文件加上bean的导入,并注释掉自动发现的component-scan

<?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">

    <!--<context:component-scan base-package="main.java.sia.knights.config.testDI"></context:component-scan>-->
    <bean id="student" class="main.java.sia.knights.config.testDI.Student"></bean>
</beans>

然后进行相同的测试,发现效果一样

通过java代码实现装配bean

先看下配置类怎么写:

package main.java.sia.knights.config.testDI;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class KnightConfig {

  @Bean
  public Student student() {
    return new Student ();
  }
}

测试类:

package main.java.sia.knights.config.testDI;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = KnightConfig.class)
public class TestDI3 {

    @Autowired
    public Student student;

    @Test
    public void testDi(){
        student.study ();
    }
}

测试结果也是相同的,大家不妨试一下。

总结

  1. 在 Spring 中装配 bean 的三种主要方式:自动化配置、基于 Java 的显式配置以及基于 XML 的显式配置。
  2. 建议尽可能使用自动化配置,以避免显式配置所带来的维护成本。但是,如果你确实需要显式配置 Spring 的话,应该优先选择基于 Java的配置,它比基于 XML 的配置更加强大、类型安全并且易于重构。

参考资料:spring in action第四版

发布了39 篇原创文章 · 获赞 1 · 访问量 4620

猜你喜欢

转载自blog.csdn.net/thetimelyrain/article/details/96653037
今日推荐