← 返回首页
Springboot自动装配原理
发表时间:2024-01-30 09:24:38
Springboot自动装配原理

Springboot自动装配原理

1.Springboot自动装配原理

在Spring Boot中,Spring Framework的IoC容器会自动扫描注解了@Component、@Service、@Repository和@Controller的类,并将它们作为Bean加入到应用上下文中。这些Bean可以在其他Bean中作为依赖注入。

实际上,SpringBoot在底层使用了一个名为BeanDefinition的东西来管理这些Bean的定义,这个BeanDefinition可以理解为一个Bean的模板,它描述了Bean的类型、作用域、是否懒加载等信息。当Spring容器启动时,它会读取这些BeanDefinition,并创建对应的Bean实例。这些Bean的信息会被保存在一个Map结构中,这个Map被称为BeanDefinitionMap。这个Map用来存储所有通过注解方式声明的Bean的定义,以便之后可以创建和管理这些Bean。这个过程是自动的,通常不需要用户干预。但如果你需要自定义Bean的创建过程,你可能需要直接操作这个BeanDefinitionMap。这通常是在创建基于代理的IoC容器时发生的,或者是在需要动态注册Bean的场景中发生的。

如果你需要查看这个Map中的内容,你可以通过实现ApplicationContextAware接口,然后访问ApplicationContext的beanFactory属性,进而访问BeanDefinitionMap。但这通常不是推荐的做法,因为这会破坏Spring的封装性,并可能导致代码与Spring的版本耦合。

2.Springboot自动装配实现

Springboot自动装配非常简单,仅仅需要在启动类上添加@SpringBootApplication注解即可。 @SpringBootApplication是一个组合注解是@SpringBootConfiguration+@EnableAutoConfiguration+@ComponentScan 三个注解的组合。

下来我们通过一个例子理解:

项目结构图如下:

1).设计CaculationStrategy接口

package com.simoniu.spt.course.service;

public interface CaculationStrategy {
    int operate(int num1,int num2);
}

2).分别设计add/sub/multi/divid四个实现了CaculationStrategy 接口的实现类。

//AddCaculationStrategyImpl.java
@Component("add")
public class AddCaculationStrategyImpl implements CaculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1+num2;
    }
}

//SubtractionStrategyImpl.java
@Component("sub")
public class SubtractionStrategyImpl implements CaculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1-num2;
    }
}

//MultipleStrategyImpl.java
@Component("multi")
public class MultipleStrategyImpl implements CaculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1*num2;
    }
}

//DividStrategyImpl.java
@Component("divid")
public class DividStrategyImpl implements CaculationStrategy {

    @Override
    public int operate(int num1, int num2) {
        return num1/num2;
    }
}

3).使用策略模式实现bean自动注入,通过工厂类实现。


import com.google.common.collect.Maps;
import com.simoniu.spt.course.service.CaculationStrategy;
import org.springframework.stereotype.Component;

import java.util.Map;

@Component
public class CaculationFactory {

    public final Map<String, CaculationStrategy> caculationStrategyMap= Maps.newHashMapWithExpectedSize(4);

    public CaculationFactory(Map<String, CaculationStrategy> strategyMap){
        System.out.println("-----strategyMap-----");
        System.out.println(strategyMap);
        this.caculationStrategyMap.clear();
        this.caculationStrategyMap.putAll(strategyMap);
    }
    public Map<String, CaculationStrategy> getCaculationStrategyMap() {
        return caculationStrategyMap;
    }
}

Guava是对Java API的补充,可以理解为是java的工具类,对Java开发中常用功能进行更优雅的实现,使得编码更加轻松,代码容易理解。需要在pom.xml添加以下依赖。

<properties>
    ...
    <guava.version>30.1-jre</guava.version>
</properties>

<dependencies>
   <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
       <version>${guava.version}</version> <!-- 请使用最新的稳定版本 -->
   </dependency>
</dependencies>

4).设计服务层

import com.simoniu.spt.course.factory.CaculationFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Service
public class CaculationService {

    @Autowired
    private CaculationFactory caculationFactory;
    public int operateByStrategy(String strategy,int num1,int num2){
        return caculationFactory.getCaculationStrategyMap().get(strategy).operate(num1,num2);
    }
}

5).controller测试自动装配


import com.simoniu.spt.course.service.CaculationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/strategy")
public class TestStrategyController {

    @Autowired
    private CaculationService caculationService;

    @GetMapping("/test/{operation}/{num1}/{num2}")
    public int testCaculation(@PathVariable String operation,@PathVariable int num1, @PathVariable int num2){
        return caculationService.operateByStrategy(operation,num1,num2);
    }
}

启动项目,我们发现add,sub,multi,divid自已经注入到IOC容器,其数据类型就是Map数据类型。

-----strategyMap-----
{add=com.simoniu.spt.course.service.impl.AddCaculationStrategyImpl@3d07df3f, divid=com.simoniu.spt.course.service.impl.DividStrategyImpl@714da74, multi=com.simoniu.spt.course.service.impl.MultipleStrategyImpl@60eeb633, sub=com.simoniu.spt.course.service.impl.SubtractionStrategyImpl@4b010b3f}

测试一个加法运算接口。