Summary:
In normal development, I don't know if you've ever thought about it. Why do we use spring's native annotations when we customize annotations (in this case, like @Component, @Service.......)), or just make a comment and use your own facet programming to implement some business logic?This article focuses on sharing how to inject IOC out of Spring's native comment custom comment
Annotation Analysis for SpringBootApplication
It is easy to see from the source code that its purpose is to automatically assemble and scan our packages and register the matching classes into containers.Auto-assembly is very simple. Without much analysis here, let's look at what is called a rule-compliant class.Definition of filter type above @ComponentScan annotation
public enum FilterType { ANNOTATION, //annotation type ASSIGNABLE_TYPE, //Specified Type ASPECTJ, //Basically not used, according to Aspectj's expression REGEX, //By regular expression CUSTOM; //custom private FilterType() { } }
excludeFilters Exclude Filters
This is for us to exclude matching classes from being used when registering with IOC. Springboot uses two exclusion filters by default. It's very simple, and you can find instructions by searching the Internet. Here I'll just lift a tesla.
package com.github.dqqzj.springboot.filter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author qinzhongjian * @date created in 2019-07-30 19:14 * @description: TODO * @since JDK 1.8.0_212-b10 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Dqqzj { String value(); }
package com.github.dqqzj.springboot.filter; import org.springframework.stereotype.Component; /** * @author qinzhongjian * @date created in 2019-07-29 22:30 * @description: TODO * @since JDK 1.8.0_212-b10 */ @Dqqzj(value = "dqqzj") @Component public class Tt { }
package com.github.dqqzj.springboot.filter; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; /** * @author qinzhongjian * @date created in 2019-07-30 19:13 * @description: TODO * @since JDK 1.8.0_212-b10 */ public class MyTypeFilter implements TypeFilter { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { if (metadataReader.getAnnotationMetadata().isAnnotated(Dqqzj.class.getName())) { return true; } return false; } }
The above code is the normal logic. Conversely, if it's okay to remove the @Component comment from the Tt class, so this exclusion comment is usually added when it's normally injectable into containers, what do we do when we said above that you can inject into containers without Spring?
IncudeFilters Contains Filters
Remove the @Component comment for the Tt class from the Spring native comment
package com.github.dqqzj.springboot.filter; import org.springframework.stereotype.Component; /** * @author qinzhongjian * @date created in 2019-07-29 22:30 * @description: TODO * @since JDK 1.8.0_212-b10 */ @Dqqzj(value = "dqqzj") //@Component public class Tt { }
See essence through phenomenon
The process combs and annotations drive the critical scan classes in the injection container (note that this refers to scans, not what @Bean, @Import, and so on, on which the rest of the annotations are built)
- ComponentScanAnnotationParser
- ClassPathBeanDefinitionScanner
- ClassPathScanningCandidateComponentProvider
ClassPathScanningCandidateComponentProvider#registerDefaultFilters
protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", cl), false)); this.logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException var4) { } try { this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", cl), false)); this.logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException var3) { } }
Annotations for @Component, JSR-250'javax.annotation.ManagedBean', JSR-330'javax.inject.Named'are registered here, so it's no surprise that our custom annotations have to have these derived annotations, to think about it differently, where they add AnnotationTypeFilter-like annotations, and where we can customize AnnotaTionTypeFilter to inject its own comments defining rules into the container.