如何理解SpringBoot的自动加载

(1)SpringBoot启动原理(被问到了QAQ)

我们开发任何一个Springboot项目都用到启动类,启动类上面会加上@SpringBootApplitcation,然后public stattic void main中,SpringApplication.run(Application.class,args)将这个标志位SpringBoot入口。

@SpringBootApplication中有三个核心的注解,其中@Configuration(其实是@SpringBootConfiguration)、@EnableAutoConfiguration、@ComponentScan

@SpringBootApplication=(默认属性)@Configuration+@EnableAutoConfiguration+@ComponentScan

 

1、@Configuration

这里的@Configuration对我们来说并陌生,他是与Spring中IOC容器配置类使用@Configuration,SpringBoot社区推荐使用基于JavaConfig的配置形式,所以这里的启动类标注了@Configuration之后,本身就变成了IOC容器配置类。

@Configuration的注解类表示了这个类可以使用SpringIOC容器作为bean定义的来源

@Bean注释告诉spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册为Spring应用程序上下文的bean定义加载到 IOC容器中。

实际上@Configuration可以立即为xml中的beans标签,而@Bean可以理解为bean标签

(1)表达层面上XML配置与JAVAConfig方式是这样的

<?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-3.0.xsd"
        default-lazy-init="true">
     <!--bean定义-->
</beans>
/这两种方式的配置是一种效果
@Configuration
public class MockConfiguration{
    //bean定义
}

(2)注册bean的定义上

<bean id="mockService" class="..MockServiceImpl">
    ...
</bean>
//任何一个标注了bean的方法,其返回值将作为一个bean的定义注册到spring IOC容器中
@Configuration
public class MockConfiguration{
    @Bean
    public MockService mockService(){
        return new MockServiceImpl();
    }
}

(3)表达依赖注入层

<bean id="mockService" class="..MockServiceImpl">
    <propery name ="dependencyService" ref="dependencyService" />
</bean>
<bean id="dependencyService" class="DependencyServiceImpl"></bean>
//如果一个bean的定义依赖其他bean,则直接调用对应的JavaConfig类中依赖bean创建方法就可以了
@Configuration
public class MockConfiguration{
    @Bean
    public MockService mockService(){
        return new MockServiceImpl(dependencyService());
    }

    @Bean
    public DependencyService dependencyService(){
        return new DependencyServiceImpl();
    }
}

最终就是这个意思

<beans> 
    <bean id = "car" class="com.test.Car"> 
        <property name="wheel" ref = "wheel"></property> 
    </bean> 
    <bean id = "wheel" class="com.test.Wheel"></bean> 
</beans>
///相当于  beans = @Configuration  bean = @bean
@Configuration
public class Conf{
    @Bean
    public Car car(){
        Car car = new Car();
        Car.setWheel(wheel());
        return car;
    }

    @Bean
    public Wheel wheel(){
        return new Wheel();
    }
}

2、@ComponentScan

@ComponentScan这个注解在Spring中很重要,他赌赢了XML配置的元素。@ComponentScan的功能其实就是自动扫描并加载到符合条件的组件中(比如@Component和@Repository)或者Bean的定义,最终将这些bean加载IOC容器中。我们可以通过BasePackge等属性来细粒度定制@ComponentScan自动扫描的范围,如果不指定,则任务spring框架会从声明出开始扫描。

3、@EnableAutoConfiguration

个人感觉@EnableAutoConfiguration这个Annotation最为重要,所以放在最后来解读。这个@Enable与@Enable开头的其他Annotation一样,比如@EnableScheduling开启定时任务、@EnableCacheing允许缓存等,其实都是接触@Import的支持,收集和注册特定场景相关的bean的定义。

~@EnableSchduling是通过@Import将Spring调度框架相关的bean定义加载IOC容器

@EnableAutoCOnfiguration也是借助@Import的帮助,将所有符合自动配置的跳江的bean定义加载IOC容器,仅此而已。@EnableAutoConfiguration会根据类路径中jar依赖为项目进行自动配置,如添加了spring-boot-starter-web依赖,会自动添加Tomcat和Spring MVC依赖,Springboot对Tomcat和spring MVC进行自动配置。

最关键要属@Import(EnableAutoConfigurationImportSelector.class)借助EnableAutoConfigurationImportSelector,可以帮助应用将所有符合条件的@Configuration配置都加载当前SpringBoot创建并使用IOC容器,哟一个spring框架中的工具类SpringFactoriesLoader,最终加载到ApplicationContext

INF/spring.factories配置问题,并将其中org.springframework.boot.autoconfigure.EnableautoConfiguration对应的配置项通过java反射实例化为对应的标注@Configuration的javaConfig形式的IOC容器配置类,然后汇总为一个并加载IOC容器中。SpringFactoriesLoader将查询配置文件命名的属性,然后进行逐个自动配置(那个文件里面各个都是配置类)。在装配一个的配置时,首先读取项目中的配置,只有项目中没有相关配置的时候才启用配置的默认值。

这也是其中最核心的一步:通过@EnableAutoConfiguration获取所有的配置以及其他形式的IOC容器配置加载到已经准备完毕ApplicationContext

原理:springboot进行实例化时SpringFactoriesLoader加载META-INF/spring.factories文件,将配置文件载入到spring容器。会过滤出key为org.springframe.boot.autoconfigure.EnableConfiguration全限定名对应的值。(最主要的注解就是@enableAutoConfiguration,而这个注解会导入一个EnableAutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories下key为EnableAutoConfiguration全限定名对应值.)     收集配置文件中配置工厂类

总结: 第一部分进行SpringApplication初始化,配置基本的环境变量、资源、构造器、监听器。  第二部分实现了具体应用的启动方案,包括启动流程的监听模块,加载配置环境模块,以及核心的创建上下文模块  第三部分才是自动化配置模块,该模块作为spring自动配置的核心。

最后还是要说一下再springboot应用程序入口:使用的@SpringBootApplication分为三个注解

@EnableAutoConfiguration:springboot根据应用所声明的依赖来对spring框架进行制动配置

@SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的xml配置文件中,装配所有bean事务,提供一个spring上下文环境。

@ComponentScan:组件扫描,可以自动发现和装配bean,默认扫描SpringApplication的run方法所在包路径下的所有配置。

Spring查看(CLASSPATH可用框架)已存在的应用程序配置,再此基础上,SpringBoot提供配置应用程序的框架所需要的基本配置,这就是自动配置。

 

接下来自己写一下吧QAQ  照着网上看的

1、配置属性类:其实就是值对象注入的方式去配置一些spring常用配置,我们编写一个最简单的配置对象

@ConfigurationProperties(prefix = "hello")
//@Conponent如果这里填了注解那么自动配置类的时候就不用添加了@enableConfigurationProperties(HelloProperties.class)
public class HelloProperties{
    private String msg ="default";
    
    public String getMsg(){
        return msg;
    }
    public void setMsg(String msg){
        this.msg = msg;
    }
}

 这是一个简单的属性值对象,那么相当于写死的字段就是SpringBoot为我们自动配置的配置,那么我们很多时候就是在自己的application。properties中修改某些配置就是这样的道理,我们不设置就是默认的。

2、自动配置

上面我们构建了简单的属性对象,那么现在我们要通过属性对象的到相应的属性值将其注入到我们bean中,这些bean就是一些SpringBoot启动后为我们自动配置生成的bean,当然SpringBoot优先使用我们配置的Bean这个功能是如何实现的。

//@Component 这是很重要,如果我们添加了这个注解那么,按照我们下面的设置SpringBoot会优先使用我们配置的这个bean,这是符合SpringBoot框架优先使用自动优先使用我们配置的这个Bean,这个符合SpringBoot优先使用自定义Bean的原则的。
public class HelloService{
    private String msg = "Service";//如果自动配置没有读入成功,那么为默认值
    public String say(){
        return "hello"+msg;
    }

    public String getMsg(){
        return msg;
    }

    public void setMsg(String msg){
        this.msg = msg;
    }
}

现在编写我们的自动配置类

@Configuration//配置类
@EnableConfigurationProperties(HelloProperties.class)//这里就是前面说的,这个注解读入我们配置对象类
@ConditionalOnClass(HelloService.class)//当类路径存在这个类时才会加载配置类,否则跳过,这个很有用比如不同的jar包间依赖,依赖的类不存在直接跳过,不会报错。
public class HelloAutoConfiguration{
    @Autowired
    private HelloProperties helloProperties;

    @Bean
    @ConditionalOnMissingBean(HelloService.class)//这个配置类就是SpringBoot可以优先使用自定义Bean的核心所在,如果没有我们的自定义bean那么才会自动配一个新的Bean
    public HelloService auto(){
        HelloService helloService = new HelloService();
        helloService.setMsg(helloProperties.getMsg());
        return helloService;
    }
}

3、测试自动配置

@SpringBootApplication
@RestController
public class MyRun{
    @Autowired
    private HelloService helloService;

    @RequestMapping("/auto/home")
    public String home(){
        return helloService.say();
    }

    public static void main(String[] args){
        SpringApplication.run(MyRun.class,args);
    }
}

ok运行后就会有  hello world

还是再说一遍Springboot管理自动配置的过程:

其实在很多时候我们的配置是在很多jar包中的,那么我们新的应用该怎么读入这些Jar里面的配置文件呢,SpringBoot是这样管理的。  最胡要的注解就是@EnableAutoConfiguration,而这个注解会导入一个EnableAutoConfigurationSelector的类,这个类会去读取一个spring.factories下key为EnableAutoConfiguration全限定名对应值。

再说一下@Service与@Service类似的还要很多@Component、@Controller、@。。。。与@Autowired\

@Service在类前注释,将此类实例化,等同于在root-context中配置,就是一个实例化放入工厂的过程

<bean class=".................."></bean>

@Autowired在属性前配置,将属性对应的对象从工厂中取出并注入到该bean中,等同于property属性中

<property ref="myImpl" name="myImpl"></property>

两个注解联合起来等同于

<bean class="................">

        <property ref="myImpl" name="myImpl"></property>

</bean>

 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值