springboot Analysis of @SpringBootApplication comment

  First is the entry application class code springboot  

@SpringBootApplication
public class HelloApplication {

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

  @SpringBootApplication annotated source code

  

/ ** 
* This class is a current project springboot 
* / 
target // standard used by the comment, classes, interfaces, abstract classes and other
@Target (ElementType.TYPE)
// declare the comment period for the run-
@Retention (RetentionPolicy .RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan (excludeFilters @Filter = {(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter (type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)})
@interface SpringBootApplication {public
    ......
}

  It can be seen that the comment is a combination of notes, mainly by @ SpringBootConfiguration, @ EnableAutoConfiguration, @ ComponentScan consisting of three notes, let's analyze one by one the three notes.

  @SpringBootConfiguration

/ ** 
* indicates a current class SpringBoot application 
* / 
@Target (ElementType.TYPE) 
@Retention (RetentionPolicy.RUNTIME) 
@Documented 
@Configuration 
public @interface SpringBootConfiguration { 

	@AliasFor (Annotation = Configuration.class) 
	Boolean proxyBeanMethods () to true default; 

}

  It can be seen from the annotation function is denoted @SpringBootConfiguration current class is a SpringBoot configuration, the main method in class so SpringBoot project bean can be injected by way of @Bean.

   @EnableAutoConfiguration  

/ ** 
 * Spring Application Context starts automatically configured by introducing a jar (to starter mode), automatic configuration needs to guess 
 * of the bean 
 * use @SpringBootApplication annotations will automatically open configuration context 
 * / 
@Target (the ElementType .TYPE) 
@Retention (RetentionPolicy.RUNTIME) 
@Documented 
@Inherited 
@AutoConfigurationPackage 
@Import (AutoConfigurationImportSelector.class) 
public @interface EnableAutoConfiguration { 

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; 

	/ ** 
	 * Auto-Configuration Exclude specific classes SUCH . that they will never be applied to exclude certain classes of automatic configuration, so that it never applied 
	 * the classes to the exclude @return 
	 * / 
	class [] the exclude () {} default <?>; 

	/ **
	 * Exclude specific auto-configuration class names such that they will never be automatically configured to exclude a specific class name, so that it never applied 
	 * Applied. 
	 * @Return at The class names to the exclude 
	 * @Since 1.3.0 
	 * / 
	String [] excludeName () {} default; 

}

  The Spring annotation is similar to other common annotations, like literally automatically configured to open, but the comment still is a combination of notes, consisting of two notes one @ AutoConfigurationPackage, @ Import

  @AutoConfigurationPackage

/ ** 
* indicates automatic configuration packet 
* @Import annotation indicating the import container AutoConfigurationPackages.Registrar 
* / 
@Target (ElementType.TYPE) 
@Retention (RetentionPolicy.RUNTIME) 
@Documented 
@Inherited 
@Import (AutoConfigurationPackages.Registrar.class) 
@interface AutoConfigurationPackage {public 

}

  AutoConfigurationPackages source See blog ( https://blog.csdn.net/andy_zhang2007/article/details/78652907 ) 

/ ** 
 * Class for Storing Auto-Configuration Reference Packages for later 
 * (EG by JPA Entity Scanner). 
 * Automatically configured for storing packets for later reference abstract class (e.g., JPA entity scanner) 
 * / 
public abstract AutoConfigurationPackages {class 
	// log slfj 
	Private static Logger = Final LogFactory.getLog the log (AutoConfigurationPackages.class); 

	Private static String BEAN = Final AutoConfigurationPackages.class.getName (); 

	/ ** 
	 * The IF the Determine Base Packages for Auto-Configuration The gIVEN 
     * bean factory are available. 
     * determined automatically given configuration bean plants basic package is available 
	 * @param bean factory beanFactory the Source 
	 * @return to true iF there are Auto-config packages available 
	 * /
	public static boolean has(BeanFactory beanFactory) {
		return beanFactory.containsBean(BEAN) && !get(beanFactory).isEmpty();
	}

	/**
	 * Return the auto-configuration base packages for the given bean factory.
	 * 返回给定bean工厂的自动配置基本包
	 * @param beanFactory the source bean factory
	 * @return a list of auto-configuration packages
	 * @throws IllegalStateException if auto-configuration is not enabled
	 */
	public static List<String> get(BeanFactory beanFactory) {
		try {
			return beanFactory.getBean(BEAN, BasePackages.class).get();
		}
		catch (NoSuchBeanDefinitionException ex) {
			throw new IllegalStateException("Unable to retrieve @EnableAutoConfiguration base packages");
		}
	}

	/**
	 * Programmatically registers the auto-configuration package names. Subsequent
	 * invocations will add the given package names to those that have already been
	 * registered. You can use this method to manually define the base packages that will
	 * be used for a given {@link BeanDefinitionRegistry}. Generally it's recommended that
	 * you don't call this method directly, but instead rely on the default convention
	 * where the package name is set from your {@code @EnableAutoConfiguration}
	 * configuration class or classes.
	 * @param registry the bean definition registry
	 * @param packageNames the package names to set
	 */
	public static void register(BeanDefinitionRegistry registry, String... packageNames) {
		if (registry.containsBeanDefinition(BEAN)) {
			BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
			ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
			constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
		}
		else {
			GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
			beanDefinition.setBeanClass(BasePackages.class);
			beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
			beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			registry.registerBeanDefinition(BEAN, beanDefinition);
		}
	}

	private static String[] addBasePackages(ConstructorArgumentValues constructorArguments, String[] packageNames) {
		String[] existing = (String[]) constructorArguments.getIndexedArgumentValue(0, String[].class).getValue();
		Set<String> merged = new LinkedHashSet<>();
		merged.addAll(Arrays.asList(existing));
		merged.addAll(Arrays.asList(packageNames));
		return StringUtils.toStringArray(merged);
	}

	/**
	 * {@link ImportBeanDefinitionRegistrar} to store the base package from 
	 * the importing configuration.
	 * 用于存储导入配置的基本包
	 */
	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImport(metadata).getPackageName());
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImport(metadata));
		}

	}

	/**
	 * Wrapper for a package import.
	 * 包装导入的包
	 */
	private static final class PackageImport {

		private final String packageName;

		PackageImport(AnnotationMetadata metadata) {
			this.packageName = ClassUtils.getPackageName(metadata.getClassName());
		}

		String getPackageName() {
			return this.packageName;
		}

		@Override
		public boolean equals(Object obj) {
			if (obj == null || getClass() != obj.getClass()) {
				return false;
			}
			return this.packageName.equals(((PackageImport) obj).packageName);
		}

		@Override
		public int hashCode() {
			return this.packageName.hashCode();
		}

		@Override
		public String toString() {
			return "Package Import " + this.packageName;
		}

	}

	/**
	 * Holder for the base package (name may be null to indicate no scanning).
	 */
	static final class BasePackages {

		private final List<String> packages;

		private boolean loggedBasePackageInfo;

		BasePackages(String... names) {
			List<String> packages = new ArrayList<>();
			for (String name : names) {
				if (StringUtils.hasText(name)) {
					packages.add(name);
				}
			}
			this.packages = packages;
		}

		List<String> get() {
			if (!this.loggedBasePackageInfo) {
				if (this.packages.isEmpty()) {
					if (logger.isWarnEnabled()) {
						logger.warn("@EnableAutoConfiguration was declared on a class "
								+ "in the default package. Automatic @Repository and "
								+ "@Entity scanning is not enabled.");
					}
				}
				else {
					if (logger.isDebugEnabled()) {
						String packageNames = StringUtils.collectionToCommaDelimitedString(this.packages);
						logger.debug("@EnableAutoConfiguration was declared on a class in the package '" + packageNames
								+ "'. Automatic @Repository and @Entity scanning is enabled.");
					}
				}
				this.loggedBasePackageInfo = true;
			}
			return this.packages;
		}

	}

}

  @Import(AutoConfigurationImportSelector.class)

    @Import represents import element AutoConfigurationImportSelector class.

      AutoConfigurationImportSelector represents the vessel is introduced a lot of automatic configuration class (xxxAutoConfiguration), all the components introduced into the container to the desired scene, and these components configure

     @ComponentScan range scan package configuration, the default scan package and its sub-packets of the current class is.

  Summary: @SpringBootApplication comment springboot is the core of the project, which is a combination of annotation notes, a combination of @ SpringBootConfiguration, @ EnableAutoConfiguration, @ ComponentScan three notes together, @ SpringBootConfiguration notes that the current class as a SpringBoot class configuration, it is possible in the current class injecting assembly into the container by way @Bean, @ EnableAutoConfiguration comment is automatically turned showing configuration, SpringBoot our guess we import the necessary components according to the initiator, and help us to automatically import configuration, @ ComponentScan scan showing the configuration package range, the current class is the default scan package, as well as its sub-packets.

  (Due to the limited level of the author's understanding of SpringBoot's not impressive enough, with the future of learning, we will continue to modify the contents of the blog, perfect.)

 

  

  

Guess you like

Origin www.cnblogs.com/onsim/p/12659440.html