Spring再次学习(1)

2019-08-09 00:00:00 spring 学习 再次

时隔一年多,在掌握了Spring、SpringBoot、SpringCloud之后

我再次回头,重新学习Spring框架

 

回顾以前的内容:

 

组件注册:

最早使用,是XML的方式:

导入依赖:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>

 

一个实体类:

《Spring再次学习(1)》
《Spring再次学习(1)》

package org.dreamtech.bean;

public class Person {

    private String name;
    private Integer age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

View Code

 

XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="person" class="org.dreamtech.bean.Person">
        <property name="name" value="张三"/>
        <property name="age" value="18"/>
    </bean>
</beans>

 

测试类:

package org.dreamtech;

import org.dreamtech.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Person bean = (Person) applicationContext.getBean("person");
        System.out.println(bean);
    }
}

 

打印:

Person{name='张三', age=18}

 

完成

 

后来,开始使用注解方式,不需要XML配置

 

写一个配置类:

package org.dreamtech.config;

import org.dreamtech.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类
 */
@Configuration
public class MainConfig {

    @Bean
    public Person person(){
        return new Person("李四",20);
    }

}

 

测试类:

package org.dreamtech;

import org.dreamtech.bean.Person;
import org.dreamtech.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}

 

打印:

Person{name='李四', age=20}

 

 

扫描Bean:扫描@Controller@Service等

在XML中的方式是:

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

注解方式是:

@ComponentScan(value = "org.dreamtech")

 

根据我们开发常用的架构,新建类:

package org.dreamtech.controller;

import org.springframework.stereotype.Controller;

@Controller
public class BookController {
}
package org.dreamtech.service;

import org.springframework.stereotype.Service;

@Service
public class BookService {
}
package org.dreamtech.dao;

import org.springframework.stereotype.Repository;

@Repository
public class BookDao {
}

 

然后查看Spring容器中所有的Bean:

package org.dreamtech.test;

import org.dreamtech.config.MainConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IOCTest {
    @Test
    public void test() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }
}

 

打印如下:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
bookController
bookDao
bookService
person

 

在扫描的时候,可以进行过滤,指定哪些需要扫描,哪些不需要:

比如我想排除Controller注解类的扫描:

@ComponentScan(value = "org.dreamtech", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})

测试成功

 

比如我只想扫描Controller注解类:

@ComponentScan(value = "org.dreamtech", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})

测试失败

 

原因:需要禁用掉默认扫描规则

@ComponentScan(value = "org.dreamtech", includeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})},
        useDefaultFilters = false)

 

以上是按照注解进行过滤的,实际上还有很多其他的方式,但是不经常使用

比如:指定类、AspectJ表达式、正则表达式、自定义

 

排除指定类(包括子类等)

@ComponentScan(value = "org.dreamtech", excludeFilters = {
        @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),
        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})}
       )

 

值得关注的是自定义规则:需要实现一个TypeFilter接口

我自定义只能扫描到包含字符串”er”的类

package org.dreamtech.config;

import org.dreamtech.bean.Person;
import org.dreamtech.service.BookService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.stereotype.Controller;

/**
 * 配置类
 */
@Configuration
@ComponentScan(value = "org.dreamtech", includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})},
        useDefaultFilters = false
)
public class MainConfig {

    @Bean
    public Person person() {
        return new Person("李四", 20);
    }

}
package org.dreamtech.config;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
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;

public class MyTypeFilter implements TypeFilter {
    /**
     * 实现
     *
     * @param metadataReader        当前正在扫描的类
     * @param metadataReaderFactory 可以获取到其他任何类的信息
     * @return 是否匹配
     * @throws IOException 异常
     */
    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;
    }
}

测试后打印:

[-------------org.dreamtech.bean.Person-------------]
[-------------org.dreamtech.config.MyTypeFilter-------------]
[-------------org.dreamtech.controller.BookController-------------]
[-------------org.dreamtech.dao.BookDao-------------]
[-------------org.dreamtech.MainTest-------------]
[-------------org.dreamtech.service.BookService-------------]
[-------------org.dreamtech.test.IOCTest-------------]
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService

 

相关文章