写点什么

Spring Boot 工程结构

用户头像
韩斌
关注
发布于: 2021 年 03 月 10 日

官方推荐


官方文档中, Spring 官方建议我们正确使用“default” 包,将 Main Application Class 放置在“default” 包下。推荐结构如下:


com +- example     +- myapplication         +- Application.java         |         +- customer         |   +- Customer.java         |   +- CustomerController.java         |   +- CustomerService.java         |   +- CustomerRepository.java         |         +- order             +- Order.java             +- OrderController.java             +- OrderService.java             +- OrderRepository.java
复制代码


在这个结构的基础上,Main 函数强烈建议放置在 com.example.myapplication 这个"default" 包路径下。这种情况下,Main 方法的类只需要如下书写即可:


package com.example.myapplication;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
}
复制代码


原因探究


这个结构有什么好处呢?可以看到上面启动类中,类上面只有一个注解@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有做比较详细的介绍,点这里查看


  • @EnableAutoConfiguration: 开启自动配置。

  • @ComponentScan: 开启包路径扫描,默认情况下会扫描当前包和子包的@Service, @Controller@Component等注解。

  • @Configuration: 允许在上下文中注册其他的 Bean 或者导入其他配置类。


强调 Main Class 一定要放在“default” 包下,就是因为只有这样,@ComponentScan才能扫描到所有的注解。


再看@SpringBootApplication的内容代码,使用@SpringBootApplication的属性exclude,excludeName,scanBasePackages, scanBasePackageClasses, nameGenerator, proxyBeanMethods就可以完成@EnableAutoConfiguration, @ComponentScan以及@Configuration的属性自定义。


/**	 * Exclude specific auto-configuration classes such that they will never be applied.	 * @return the classes to exclude	 */	@AliasFor(annotation = EnableAutoConfiguration.class)	Class<?>[] exclude() default {};
/** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ @AliasFor(annotation = EnableAutoConfiguration.class) String[] excludeName() default {};
/** * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses} * for a type-safe alternative to String-based package names. * <p> * <strong>Note:</strong> this setting is an alias for * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity} * scanning or Spring Data {@link Repository} scanning. For those you should add * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and * {@code @Enable...Repositories} annotations. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {};
/** * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to * scan for annotated components. The package of each class specified will be scanned. * <p> * Consider creating a special no-op marker class or interface in each package that * serves no purpose other than being referenced by this attribute. * <p> * <strong>Note:</strong> this setting is an alias for * {@link ComponentScan @ComponentScan} only. It has no effect on {@code @Entity} * scanning or Spring Data {@link Repository} scanning. For those you should add * {@link org.springframework.boot.autoconfigure.domain.EntityScan @EntityScan} and * {@code @Enable...Repositories} annotations. * @return base packages to scan * @since 1.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {};
/** * The {@link BeanNameGenerator} class to be used for naming detected components * within the Spring container. * <p> * The default value of the {@link BeanNameGenerator} interface itself indicates that * the scanner used to process this {@code @SpringBootApplication} annotation should * use its inherited bean name generator, e.g. the default * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the * application context at bootstrap time. * @return {@link BeanNameGenerator} to use * @see SpringApplication#setBeanNameGenerator(BeanNameGenerator) * @since 2.3.0 */ @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator") Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/** * Specify whether {@link Bean @Bean} methods should get proxied in order to enforce * bean lifecycle behavior, e.g. to return shared singleton bean instances even in * case of direct {@code @Bean} method calls in user code. This feature requires * method interception, implemented through a runtime-generated CGLIB subclass which * comes with limitations such as the configuration class and its methods not being * allowed to declare {@code final}. * <p> * The default is {@code true}, allowing for 'inter-bean references' within the * configuration class as well as for external calls to this configuration's * {@code @Bean} methods, e.g. from another configuration class. If this is not needed * since each of this particular configuration's {@code @Bean} methods is * self-contained and designed as a plain factory method for container use, switch * this flag to {@code false} in order to avoid CGLIB subclass processing. * <p> * Turning off bean method interception effectively processes {@code @Bean} methods * individually like when declared on non-{@code @Configuration} classes, a.k.a. * "@Bean Lite Mode" (see {@link Bean @Bean's javadoc}). It is therefore behaviorally * equivalent to removing the {@code @Configuration} stereotype. * @since 2.2 * @return whether to proxy {@code @Bean} methods */ @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true;
复制代码


小结


Spring Boot 官方推荐的工程结构在大部分情况下都适用,用这个结构也是最保险的。如果有特殊情况,务必要记得配置@ComponentScan 的包路径。


发布于: 2021 年 03 月 10 日阅读数: 7
用户头像

韩斌

关注

还未添加个人签名 2018.03.24 加入

还未添加个人简介

评论

发布
暂无评论
Spring Boot工程结构