Use Spring (a) the source of the @ Configuration, @ ComponentScan, @ Bean's

In recent consolidation of some spring relevant knowledge, incidentally, just look at this record sum up, to see for himself want to help some are learning and have been learning partner.

In this article @Configuration records about the use of annotations and xml file and how it corresponds.

Since spring3.0 start, @ Configuration may be used to define the configuration, that is, replace the past xml configuration, inner class annotated Bean containing one or more, these methods are loaded AnnotationConfigWebApplicationContext AnnotationConfigApplicationContext or scanning, and construct from the initialization Bean spring container, similar to load the xml file ClassPathXmlApplicationContext class load xml file.

First, the use of @ Bean: Using this annotation indicating a register in a container Bean, the method returns a value of type Type, id defaults to the method name, id may be specified on their own, like a set of <bean> in xml </ bean> tag, give a simple example:

 <bean id="person" class="bean.Person">
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
 </bean>

Use the xml

First, create a class and registered in xml a Bean, id as a person, class write the full path, and defines two properties name and age,

In the past we loaded through ClassPathXmlApplicationContext xml file, according to the bean id specified by getBean (id) to get to Bean, for example:

public class MainTes {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Person bean = (Person) applicationContext.getBean("person");
        System.out.println("person:"+bean);
        //打印信息:person:Person{name='张三', age='18'}
    }
}

@Bean use annotation:

We need to customize a class @Configuration be designated as a configuration class equivalent to the xml file <beans> </ beans>, we registered in the class Bean

//配置类==配置文件
@Configuration //告诉spring这是一个配置类
public class MainConfig {
    @Bean(name = "person")  //在容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id,也可以自己指定name属性为id类型
    public Person person(){
        return new Person("李四","16");
    }
}

By scanning the class loading AnnotationConfigApplicationContext

public class MainTes {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        //根据返回值类型来得到Bean
        Person bean = applicationContext.getBean(Person.class);
        //根据id来得到Bean
        Person bean1 = (Person) applicationContext.getBean("person");
        //获取bean的id,也就是@Bean(name="person")中name的值,没有的话就默认为方法名作为id。
        String[] str = applicationContext.getBeanNamesForType(Person.class);
        for (String st : str) {
            System.out.println("str:" + st);
        }
        System.out.println("bean:" + bean);
        System.out.println("bean1:" + bean1);
//        打印信息:
//        str:person
//        bean:Person{name='李四', age='16'}
//        bean1:Person{name='李四', age='16'}
    }
}

We can load and get the container Bean

That

Xml @Configuration equivalent of <beans> </ beans>

@Bean equivalent to the xml <bean> </ bean>

Second, the package scanning components: long marked @ Controller, @ Service, @ Respository, @ Component will be scanned

In the xml configuration is such <context: component-scan bse-package = ""> </ context: component-scan>, we are generally written in the package when the specified base-package root directory, because it automatically All packages scan the root directory, as long as the label for more than four annotation will be scanned.

 <context:component-scan base-package="bean"></context:component-scan>
    <bean id="person" class="bean.Person">
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
 </bean>

I mainly look at this record @ComponentScan use:

@ComponentScan xml configuration file is equivalent to the above scanning unit: automatically scan all of the following package path @ Controller, @ Service, @ Repository, @ Component Class

@ComponentScan in the property: value specified scanning package, includeFilters include those filters, excludeFilters does not include those filters, useDefaultFilters default filter rules are turned on, if we want to customize the words are to be closed. Wherein a filter is @Filters interface.

value attributes : opening the annotation defined class ComponentScan spring we can find value property defaults to a String [] type

Value may be a value typically scan package name:

First, I create a separate dao, service, controller, respectively, in three different packages, pay attention to look at the package name, I watch it for the convenience, they will be integrated into three classes together.

package dao;
import org.springframework.stereotype.Repository;
@Repository
public class TestDao {}

/*----------------------------------------------*/

package Controller;
import org.springframework.stereotype.Controller;
@Controller
public class TestController {}


/*----------------------------------------------*/

package service;
import org.springframework.stereotype.Service;
@Service
public class TestService {}

My scan Controller, dao, service notes

//配置类==配置文件
@Configuration //告诉spring这是一个配置类
//扫描策略
@ComponentScan(value = {"Controller","dao","service"}) //也可以根目录扫描的方式,会自动扫描目录下带有4个注解的包
public class MainConfig {}
public class AnnoTest {
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(MainConfig.class);
        String[] definition = applicationContext.getBeanDefinitionNames();
        for(String name : definition){
            System.out.println("name:"+name);
            //在打印的信息中我们可以看到上方标注了@Controller @Service @Repository的类名
        }
    }
}

excludeFilters: filters, filter rules are defined, corresponding to <context: component-scan bse-sub-tags within </ context component-scan> <"/> the main filter rules:

FilterType.ANNOTATION: According to notes

FilterType.ASSIGNABLE_TYPE: according to the given type

FilterType.ASPECTJ: Use ASPECTJ expression

FilterType.REGEX: Use regular

FilterType.CUSTOM: Use custom rules

For example: type is in accordance with the annotation type, value is specified in the annotation name is not being scanned, so we can skip class with two notes at the time of scanning.

//配置类==配置文件
@Configuration //告诉spring这是一个配置类
//扫描策略
@ComponentScan(value = {"Controller","dao","service"},excludeFilters ={
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class,Service.class}), //按照注解来过滤
}) //也可以根目录扫描的方式,会自动扫描目录下带有4个注解的包
public class MainConfig {

}

We see the spring we can find the definition of annotation ComponentScan Filter, we can see that spring is the default filter rules annotation mode, opening the FilterType we can find several spring defined filtering rules.

includeFilters: and excludeFilters opposite effect, just scan the scan package, but note that the use of this when the need to specify the default scan userDefaultFilters = false rule is false, because the default is true not take effect.

@ComponentScan(value = {"Controller","dao","service"},includeFilters ={
        @ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class,Service.class}), //按照注解来过滤
},useDefaultFilters = false) //也可以根目录扫描的方式,会自动扫描目录下带有4个注解的包
public class MainConfig {

}

FilterType.CUSTOM: custom scan rules a little this important point.

We need to customize and override TypeFilter achieve a match Filter method, according to the method returns a Boolean true or false to determine whether the filter.

For example: Filter Type specified custom type, a value of its own class definition

//配置类==配置文件
@Configuration //告诉spring这是一个配置类
//扫描策略
@ComponentScan(value = {"Controller","dao","service"},excludeFilters ={
        @ComponentScan.Filter(type = FilterType.CUSTOM,value = {MyFilter.class}) //由自定义的Filter返回的布尔值来过滤
})
public class MainConfig {

}
public class MyFilter implements TypeFilter {
    /**
     * @param metadataReader 读取到的当前正在扫描的类的信息
     * @param metadataReaderFactory  获取其他任何类的信息
     * @return
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        //获取当前按正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前类资源(类的路径)
        Resource resource = metadataReader.getResource();
        String className = classMetadata.getClassName();
        System.out.println("---->"+className);
        if(className.contains("er")){
            return true;
        }
        return false;
    }
}
public class AnnoTest {
    @SuppressWarnings("resource")
    @Test
    public void test01(){
        ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(MainConfig.class);
        String[] definition = applicationContext.getBeanDefinitionNames();
        for(String name : definition){
            System.out.println("name:"+name);
        }
    }
}

Print information:

---->Controller.TestController
---->dao.d.TesDao1
---->dao.d1.TesDao2
---->dao.TestDao
---->service.TestService

name:tesDao1
name:tesDao2
name:testDao

We can see the scan class has five, but as long as marked @Repository is not filtered, @ Controller and @Service have been filtered out because they package the "er".

Record study notes be forced to make their own learning and encouragement, but also want to be able to help those in need of partners to note what is wrong or lack of hope that we can help to correct. Many thanks!

 

Published 17 original articles · won praise 18 · views 1038

Guess you like

Origin blog.csdn.net/qq_40409260/article/details/103056959