1. 程式人生 > >@SpringBootApplication註解分析

@SpringBootApplication註解分析

首先我們分析的就是入口類Application的啟動註解@SpringBootApplication,進入原始碼:

複製程式碼
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
....
}
複製程式碼

發現@SpringBootApplication是一個複合註解,包括@ComponentScan,和@SpringBootConfiguration@EnableAutoConfiguration

  • @SpringBootConfiguration繼承自@Configuration,二者功能也一致,標註當前類是配置類,並會將當前類內宣告的一個或多個以@Bean註解標記的方法的例項納入到srping容器中,並且例項名就是方法名。
  • @EnableAutoConfiguration的作用啟動自動的配置,@EnableAutoConfiguration註解的意思就是Springboot
    根據你新增的jar包來配置你專案的預設配置,比如根據spring-boot-starter-web ,來判斷你的專案是否需要添加了webmvctomcat,就會自動的幫你配置web專案中所需要的預設配置。在下面部落格會具體分析這個註解,快速入門的demo實際沒有用到該註解。
  • @ComponentScan,掃描當前包及其子包下被@Component@Controller@Service@Repository註解標記的類並納入到spring容器中進行管理。是以前的<context:component-scan>(以前使用在xml中使用的標籤,用來掃描包配置的平行支援)。所以本demo中的User為何會被spring
    容器管理。

根據上面的理解,上面的入口類Application,我們可以使用:

package com.zhihao.miao;
import com.zhihao.miao.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import java.util.Map;

@ComponentScan
public class Application {

    @Bean
    public Runnable createRunnable(){
        return () -> System.out.println("spring boot is running");
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
        context.getBean(Runnable.class).run();
        System.out.println(context.getBean(User.class));
        Map map = (Map) context.getBean("createMap");
        int age = (int) map.get("age");
        System.out.println("age=="+age);

    }
}

使用@ComponentScan註解代替@SpringBootApplication註解,也可以正常執行程式。原因是@SpringBootApplication中包含@ComponentScan,並且springboot會將入口類看作是一個@SpringBootConfiguration標記的配置類,所以定義在入口類Application中的Runnable也可以納入到容器管理。

SpringBootApplication引數詳解


圖片.png
  • Class<?>[] exclude() default {}:
    根據class來排除,排除特定的類加入spring容器,傳入引數value型別是class型別。
  • String[] excludeName() default {}:
    根據class name來排除,排除特定的類加入spring容器,傳入引數value型別是class的全類名字串陣列。
  • String[] scanBasePackages() default {}:
    指定掃描包,引數是包名的字串陣列。
  • Class<?>[] scanBasePackageClasses() default {}:
    掃描特定的包,引數類似是Class型別陣列。

看一個demo學會使用這些引數配置
在包下com.zhihao.miao.springboot定義一個啟動應用類(加上@SpringBootApplication註解)

package com.zhihao.miao.springboot;


import com.zhihao.miao.beans.Cat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        Cat cat = context.getBean(Cat.class);
        System.out.println(cat);
    }
}

在com.zhihao.miao.beans包下定義一個實體類,並且想將其納入到spring容器中,

public class Cat {
}
package com.zhihao.miao.beans;

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

@Configuration
public class MyConfig {

    @Bean
    public Cat cat(){
        return new Cat();
    }

}

啟動啟動類,列印結果如下:


 

說明Cat類並沒有納入到spring容器中,這個結果也如我們所想,因為@SpringBootApplication只會掃描@SpringBootApplication註解標記類包下及其子包的類(特定註解標記,比如說@Controller,@Service,@Component,@Configuration和@Bean註解等等)納入到spring容器,很顯然MyConfig不在@SpringBootApplication註解標記類相同包下及其子包的類,所以需要我們去配置一下掃包路徑。

修改啟動類,@SpringBootApplication(scanBasePackages = "com.zhihao.miao"),指定掃描路徑:

package com.zhihao.miao.springboot;

import com.zhihao.miao.beans.Cat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication(scanBasePackages = "com.zhihao.miao")
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        Cat cat = context.getBean(Cat.class);
        System.out.println(cat);
    }
}

啟動並列印:


 

當然使用@SpringBootApplication(scanBasePackageClasses = MyConfig.class),指定scanBasePackageClasses引數的value值是你需要掃描的類也可以,結果一樣,不過如果多個配置類不在當前包及其子包下,則需要指定多個。

再看一個列子,
在上面的列子的相同包下(com.zhihao.miao.springboot)配置了People,並將其納入到spring容器中(@Component),我們知道@SpringBootApplication註解會掃描當前包及其子包,所以People類會納入到spring容器中去,我們需要將其排除在spring容器中,如何操作?
可以使用@SpringBootApplication的另外二個引數(exclude或excludeName)

package com.zhihao.miao.springboot;

import org.springframework.stereotype.Component;

@Component
public class People {
}

啟動類,

package com.zhihao.miao.springboot;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        People people = context.getBean(People.class);
        System.out.println(people);
    }
}

啟動並列印結果:


 

然後修改@SpringBootApplication配置,

package com.zhihao.miao.springboot;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication(exclude = People.class)
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =SpringApplication.run(Application.class,args);
        People people = context.getBean(People.class);
        System.out.println(people);
    }
}

很明顯啟動報錯。使用@excludeName註解也可以。如下,
@SpringBootApplication(excludeName = {"com.zhihao.miao.springboot.People"})

參考文件:
Springboot1.5.4官方文件

原文地址:https://www.cnblogs.com/duanxz/p/3756364.html