current position:Home>Spring framework learning - path scanning and management components such as spring IOC

Spring framework learning - path scanning and management components such as spring IOC

2022-01-26 22:36:13 TyuIn

Follow up with a blog :https://blog.csdn.net/qq_43605444/article/details/121974366?spm=1001.2014.3001.5501

11、 Classpath scanning and management components

Most of the examples in this chapter use XML To specify in Spring Each... Is generated in the container BeanDefinition Configuration metadata for . Previous section ( Annotation based container configuration ) Demonstrates how to provide a large amount of configuration metadata through source level annotations . However , Even in these examples ,“ basic ”bean The definition is also XML Clearly defined in the document , Annotations only drive dependency injection .

This section describes the options for implicitly detecting candidate components by scanning the classpath . Candidate components are classes that match the filter criteria , And register the corresponding... In the container bean Definition . This eliminates the use of XML To execute bean Registration needs . contrary , You can use annotations ( for example ,@Component)、AspectJ Type expression or your own custom filter criteria to select which classes have the ability to register with the container bean Definition .

from Spring 3.0 Start ,Spring JavaConfig Many of the functions provided by the project are core Spring Framework Part of . This allows you to use Java Instead of using traditional XML File to define bean. see @Configuration、@Bean、@Import and @DependsOn annotation , Learn examples of how to use these new features .

11.1 @Component And further prototype annotations

@Repository Annotations are any implementation repository role or stereotype ( Also known as data access objects or DAO) The tag of the class . One of the uses of this tag is the automatic conversion of exceptions , As described in exception conversion .

Spring Provides more stereotype comments :@Component、@Service and @Controller. @Component Any Spring General stereotype of managed components . @Repository、@Service and @Controller yes @Component The specialization of , For more specific use cases ( In the persistence layer 、 Service layer and presentation layer ). therefore , You can use @Component Annotate your component class , however , By using @Repository、@Service or @Controller To annotate them , Your class is better suited to be handled by tools or associated with aspects .

for example , These stereotype annotations are ideal targets for pointcuts . @Repository、@Service and @Controller You can also do it in Spring Framework Future versions of will carry additional semantics . therefore , If you use in the service layer @Component or @Service Make a choice between ,@Service Obviously a better choice . Again , As mentioned earlier ,@Repository It has been supported as a marker for automatic exception conversion in the persistence layer .

11.2 Use meta annotations and composite annotations

Spring Many of the annotations provided can be used as meta annotations in your own code . Meta annotations are annotations that can be applied to another annotation . Like the one mentioned earlier @Service Annotation is to use @Component Meta annotated , As shown in the following example :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component 
public @interface Service {
    

    // ...
}

You can also combine meta annotations to create “ Combine notes ”. for example ,Spring MVC Medium @RestController Annotation is made by @Controller and @ResponseBody Composed of .

Besides , Composite annotations can optionally redeclare attributes from meta annotations to allow customization . When you only want to open a subset of meta annotation attributes , It would be particularly useful . for example ,Spring Of @SessionScope The annotation hardcodes the scope name as session , But still allow customization proxyMode. The following list shows SessionScope Definition of annotations :

@Target({
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {
    

    /** * Alias for {@link Scope#proxyMode}. * <p>Defaults to {@link ScopedProxyMode#TARGET_CLASS}. */
    @AliasFor(annotation = Scope.class)
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

then , You can use @SessionScope There is no need to state proxyMode, As shown below :

@Service
@SessionScope
public class SessionScopedService {
    
    // ...
}

You can also override proxyMode Value , This is shown in the following example :

@Service
@SessionScope(proxyMode = ScopedProxyMode.INTERFACES)
public class SessionScopedUserService implements UserService {
    
    // ...
}

For more details , see also Spring Annotation Programming Model wiki page .【https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model

11.3 Automatically detect classes and register Bean Definition

Spring You can automatically detect the stereotype class and put the corresponding BeanDefinition Instance registered to ApplicationContext. for example , The following two classes are eligible for such automatic detection :

@Service
public class SimpleMovieLister {
    

    private MovieFinder movieFinder;

    public SimpleMovieLister(MovieFinder movieFinder) {
    
        this.movieFinder = movieFinder;
    }
}
@Repository
public class JpaMovieFinder implements MovieFinder {
    
    // implementation elided for clarity
}

To automatically detect these classes and register the corresponding bean, You need to @ComponentScan Add to @Configuration Class , among basePackages Property is the common parent package of two classes . ( perhaps , You can specify a comma or semicolon or space delimited list containing the parent package of each class .)

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    
    // ...
}

For brevity , The previous example can use annotated value attribute ( namely @ComponentScan("org.example")).

The following alternatives use XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example"/>

</beans>

<context:component-scan> The use of implicitly enables <context:annotation-config> The function of . Use <context:component-scan> There is usually no need to include <context:annotation-config> Elements .

The scanning of classpath package requires the existence of corresponding directory entries in the classpath . When you use Ant structure JAR when , Please make sure you are not activated JAR File only switch for task . Besides , Based on security policies in some environments , The classpath directory may not be exposed — for example ,JDK 1.7.0_45 Standalone applications on and above ( You need to set... In the list “Trusted-Library” — see also https://stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources).

stay JDK 9 Module path (Jigsaw) On ,Spring Classpath scanning usually works as expected . however , Make sure your component class is exported in your module information descriptor . If you wish Spring Call non-public members of your class , Please make sure they are “ The open ”( namely , They are used in the module information descriptor opens Declaration, not export declaration ).

Besides , When you use components to scan elements ,AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor Are implicitly included . This means that the two components are automatically detected and connected together — None of this is in XML Provide any bean Configuration metadata .

You can include a value of false Of annotation-config Property to disable AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor Registration of .

11.4 Use the filter to customize the scan

By default , use @Component、@Repository、@Service、@Controller、@Configuration Annotated classes or themselves use @Component The custom annotation of the annotation is the only detected candidate component . however , You can modify and extend this behavior by applying custom filters . Add them as @ComponentScan Annotated includeFilters or excludeFilters attribute ( Or as XML Configuration in progress <context:component-scan> Elemental <context:include-filter /> or <context:exclude-filter /> Subelement ). Each filter element requires type and expression attribute . The following table describes the filtering options :

Filter type Example expressions describe
annotation (default) org.example.SomeAnnotation At the type level of the target component There is or Meta existence Annotations .
assignable org.example.SomeClass Target components can be assigned to ( Extend or implement ) Class ( Or interface ).
aspectj org.example..*Service+ Target component to match AspectJ Type expression .
regex org\.example\.Default.* The regular expression to match the class name of the target component .
custom org.example.MyTypeFilter org.springframework.core.type.TypeFilter Custom implementation of interface .

The following example shows ignoring all @Repository Annotate and use “ stub ” Repository configuration :

@Configuration
@ComponentScan(basePackages = "org.example",
        includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
        excludeFilters = @Filter(Repository.class))
public class AppConfig {
    
    // ...
}

The following listing shows the equivalent XML:

<beans>
    <context:component-scan base-package="org.example">
        <context:include-filter type="regex" expression=".*Stub.*Repository"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
</beans>

You can also set... On the annotation useDefaultFilters=false Or by providing use-default-filters="false" As <component-scan/> Element to disable the default filter . This effectively disables the use of @Component、@Repository、@Service、@Controller、@RestController or @Configuration Automatic detection of annotated or meta annotated classes .

11.5 Define... In a component Bean Metadata

Spring The component can also bean The definition metadata is provided to the container . You can use for @Configuration Annotation class bean The same metadata @Bean Annotation to do this . The following example shows how to do this :

@Component
public class FactoryMethodComponent {
    

    @Bean
    @Qualifier("public")
    public TestBean publicInstance() {
    
        return new TestBean("publicInstance");
    }

    public void doWork() {
    
        // Component method implementation omitted
    }
}

The previous class is a Spring Components , its doWork() Method has application specific code . however , It also provides a bean Definition , The definition has a reference method publicInstance() The factory method of . @Bean Annotations identify factory methods and other bean Defining attributes , For example, through @Qualifier The qualifier value of the annotation . Other method level annotations that can be specified are @Scope、@Lazy And custom qualifier annotations .

In addition to being used for component initialization , You can also mark as @Autowired or @Inject Place... On the injection point of @Lazy annotation . under these circumstances , It leads to the injection of lazy parsing agents . However , This proxy method is quite limited . For complex inert interactions , Especially with optional dependencies , We suggest using instead ObjectProvider<MyTargetBean>.

As mentioned earlier , Support automatic assembly fields and methods , And additional support @Bean Automatic assembly of methods . The following example shows how to do this :

@Component
public class FactoryMethodComponent {
    

    private static int i;

    @Bean
    @Qualifier("public")
    public TestBean publicInstance() {
    
        return new TestBean("publicInstance");
    }

    // use of a custom qualifier and autowiring of method parameters
    @Bean
    protected TestBean protectedInstance(
            @Qualifier("public") TestBean spouse,
            @Value("#{privateInstance.age}") String country) {
    
        TestBean tb = new TestBean("protectedInstance", 1);
        tb.setSpouse(spouse);
        tb.setCountry(country);
        return tb;
    }

    @Bean
    private TestBean privateInstance() {
    
        return new TestBean("privateInstance", i++);
    }

    @Bean
    @RequestScope
    public TestBean requestScopedInstance() {
    
        return new TestBean("requestScopedInstance", 3);
    }
}

This example will String Method parameter country Automatically assemble to another named privateInstance Of bean Upper age Property value . Spring Expression language elements are represented by symbols #{ <expression> } Define the value of the attribute . about @Value annotation , The expression parser is preconfigured to look for... When parsing expression text bean name .

from Spring Framework 4.3 Start , You can also declare the type as InjectionPoint( Or its more specific subclasses :DependencyDescriptor) Factory method parameters to access and trigger the current bean Created request injection point . Please note that , This only applies to bean The actual creation of the instance , Not applicable to injection of existing instances .

therefore , This feature is useful for prototype scope bean Most meaningful . For other ranges , The factory method will only see that the creation of a new... Is triggered within a given scope bean The injection point of the instance ( for example , Trigger the creation of lazy singletons bean The dependencies of ). under these circumstances , You can use the provided injection point metadata and pay attention to semantics . The following example shows how to use InjectionPoint:

@Component
public class FactoryMethodComponent {
    

    @Bean @Scope("prototype")
    public TestBean prototypeInstance(InjectionPoint injectionPoint) {
    
        return new TestBean("prototypeInstance for " + injectionPoint.getMember());
    }
}

routine Spring In the component @Bean The way to deal with the method is similar to Spring @Configuration The corresponding methods in the class are different . The difference is @Component Class doesn't work CGLIB Enhanced to intercept calls to methods and fields . CGLIB A proxy is a call to @Configuration Class @Bean A method of a method or field in a method , Through this method, you can create a query for the collaboration object bean Metadata reference . These methods are not ordinary Java Semantically called , It's through containers Spring bean Common life cycle management and agents , Even when called programmatically @Bean Method references other bean It's the same when .

by comparison , In general @Component In the class @Bean Methods or fields in methods have standard Java semantics , Nothing special CGLIB Processing or other constraint application .

You can use @Bean Method is declared static , Allows you to call the configuration classes it contains without creating them as instances . This is after defining the post processor bean( for example ,BeanFactoryPostProcessor or BeanPostProcessor type ) It's especially meaningful , Because of this kind of bean Initialized early in the container life cycle , And avoid triggering other parts of the configuration at that time .

Due to technical limitations , For static @Bean Method calls will never be intercepted by the container , Even in @Configuration Class will not ( As mentioned earlier in this section ):CGLIB Subclassing can only cover non static methods . therefore , To the other @Bean The direct call of method has standard Java semantics , This results in a separate instance being returned directly from the factory method itself .

@Bean Methodical Java Language visibility will not affect Spring Generated in container bean Definition has a direct impact . You can do it in non @Configuration Class and static methods anywhere, you are free to declare factory methods that you think are appropriate . however ,@Configuration General in class @Bean Methods need to be overridable — in other words , They cannot be declared as private or final.

@Bean Methods can also be found on the base class of a given component or configuration class , And declared in the interface implemented by the component or configuration class Java 8 The default method is . This provides great flexibility for combining complex configuration arrangements , from Spring 4.2 Start , Even through Java 8 The default method implements multiple inheritance .

Last , A single class can be the same bean Save multiple @Bean Method , As an arrangement of multiple plant methods , Use... Based on available dependencies at runtime . This is different from selecting... In other configuration scenarios “ Most greedy ” The algorithm of the constructor or factory method is the same : When constructing, select variants with the most satisfying dependencies , Similar to how containers work in multiple @Autowired Choose between constructors .

Article reference :https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-classpath-scanning

copyright notice
author[TyuIn],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201262236063041.html

Random recommended