springboot的自动装配

102 阅读2分钟

背景

Spring应用需要进行大量的xml配置,为了简化,springboot倡导“约定大于配置”,定义一套接口规范,根据规范在启动时会扫描外部引用jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器,并执行类中定义的各种操作。

SpringBoot中,我们可以引入starter后,通过少量注解和配置就可以使用第三方包的功能。

自动装配

@SpringBootConfiguration上有@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan这三个注解修饰,@SpringBootApplication可以看作是这三个注解作用的集合。

@EnableAutoConfiguration:启用 SpringBoot 的自动配置机制。(是实现自动装配的核心注解)

@SpringBootConfiguration:允许在上下文中注册额外的 bean 或导入其他配置类,作用与 applicationContext.xml 的功能相同。

@ComponentScan:扫描包下的类中添加了@Component(@Service,@Controller,@Repostory,@RestController)注解的类 ,并添加的到spring的容器中,可以自定义不扫描某些 bean。

几种注入bean的配置方式

  1. @Component注解:@Component 被称为元注释,它是@Repository、@Service、@Controller、@Configuration的父类,理论上可以使用@Component来注释任何需要Spring自动装配的类。

  2. @Bean注解: 搭配@Configuration/@Component使用,@bean注解是被设计使用在方法上的,在方法上使用@bean注解的时候,该方法就会被告知去产生一个bean对象,然后这个bean对象交给spring管理,且产生这个bean对象的方法在整个spring的生命周期中只会被调用一次, 调用完成之后spring会将这个bean对象放在自己的ioc容器中。注:@Configuration 搭配bean使用默认是单例模式,即使new,也是创建同一个对象,而@Component则会创建不同的对象)。

    @Configuration
    public class MyTestConfig {
    
        @Bean
        public Driver driver(){
            Driver driver = new Driver();
            driver.setId(1);
            driver.setName("driver");
            driver.setCar(car());
            return driver;
        }
        ```
        @Bean
        public Car car(){
            Car car = new Car();
            car.setId(1);
            car.setName("car");
            return car;
        }
    }
    
    测试代码如下
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class TestApplicationTests {
    
        @Autowired
        private Car car;
    
        @Autowired
        private Driver driver;
    
        @Test
        public void contextLoads() {
            boolean result = driver.getCar() == car;
            System.out.println(result ? "同一个car" : "不同的car");
        }
    
    }
    如果使用@Configuration注解,会打印出来是同一个car,如果换成@Component注解,会打印不同的car
    
  3. @Import注解: Import注解只能作用在类

    @Import(User.class)
    @Configuration
    public class Configuration01 {
    }
    
  4. 使用ImportSelector或者ImportBeanDefinitionRegistrar接口,配合@Import实现。