萤火小屋

优律的知识库

  • 首页
  • 归档
  • 分类
  • 标签
  • 留言
  • 关于

  • 搜索
消息队列 RabbitMQ Redis 双指针 力扣 动态代理 Git YAML SpringBoot SpringMVC 回溯算法 分治算法 归并排序 快排 手撕 事务 MySQL索引 MySQL 小技巧 Spring Framework Spring 动态规划 Linux Android 贪心算法 操作系统 进程调度模拟 IPv6 数据库 计算机组成原理 计算机基础 栈 Java 静态路由 路由器 交换机 数字通信 网络工程 计算机网络 Web http 大学学习技巧 程序设计 算法

Spring注解学习[email protected]注解

发表于 2022-03-08 | 分类于 Spring | 0 | 阅读次数 108

注解概括

ComponentScan注解

该注解加注在配置类上,用于告诉Spring扫描哪些包,并把这些包中加注了@Controller、@Service、@Component和@Repository的类生成bean放入到容器中。
同时,还可以指定一些过滤器来过滤不扫描或者只扫描哪些包。

Filter和FilterType

在ComponentScan注解中有两个过滤器数组,名为includeFilters和excludeFilters,它们的都是Filter数组类型,Filter其中有一个属性叫做type,它的类型是FilterType枚举类,通过给它赋值,可以定义过滤器的性质;其中value(或classes)数组可以赋值一些注解让过滤器过滤。

image.png

FilterType的类型:

  1. ANNOTATION:注解,默认值。官方注释:Filter candidates marked with a given annotation.大概意思是被指定注解注的组件会被过滤器过滤。
  2. ASSIGNABLE_TYPE:类似diy,给定什么值就过滤什么值。官方注释:Filter candidates assignable to a given type.大概意思是过滤给定的条件。
  3. ASPECTJ:aspectJ表达式,不常用。官方注释:Filter candidates matching a given AspectJ type pattern expression.
  4. REGEX:正则表达式。官方注释:Filter candidates matching a given regex pattern.
  5. CUSTOM:自定义。官方注释:Filter candidates using a given custom org.springframework.core.type.filter.TypeFilter implementation.大概意思是自己定义的类型需要实现TypeFilter接口,然后覆写match方法进行匹配。

代码演示

演示组件扫描注解配合排除过滤器

项目代码沿用上个文章

增加以下四个类
image.png

同时在这四个类上加注概括中的注解
image.png

image.png

image.png

image.png

编写测试类

package cc.fireflyhut.study;

import cc.fireflyhut.study.config.MyConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class IOCTest {

    @Test
    public void test01() {
        // 获得注解配置容器类
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        // 获取容器中所有的BeanDefinition的名字
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }

}

修改配置类

package cc.fireflyhut.study.config;

import cc.fireflyhut.study.dao.MyRepository;
import cc.fireflyhut.study.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Configuration
/*
  value值指定扫描cc.fireflyhut.study包
  excludeFilters指定排除过滤器
*/
@ComponentScan(value = "cc.fireflyhut.study.*", excludeFilters = {
        // 该过滤器指定为按注解过滤,过滤被Service注解的类和被Repository注解的类,加注两类注解的类将不再被扫描
        @Filter(type = FilterType.ANNOTATION, classes = {Repository.class, Service.class})
})
public class MyConfig {

    /**
     * 向容器中注册一个id未user类型为User的Bean
     * 该Bean的id默认为方法名(user)如果想指定id,需要在@Bean注解中传入value值指定id
     */
    @Bean
    public User user() {
        return new User("admin", "123456");
    }

    /**
     * 指定注册到容器中的bean的id为user111
     */
    @Bean("user111")
    public User user1() {
        return new User("admin", "123456");
    }

}

执行测试类测试方法打印结果
image.png
不难发现,容器中只有myController类和myComponent的单例bean了。

演示组件扫描注解配合只包括过滤器

当使用includeFilters过滤器时,需要关闭Spring默认开启的默认过滤器,只需将ComponentScan注解中的useDefaultFilters属性设置为false即可。

修改配置类

package cc.fireflyhut.study.config;

import cc.fireflyhut.study.dao.MyRepository;
import cc.fireflyhut.study.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Configuration
/*
  value值指定扫描cc.fireflyhut.study包
  excludeFilters指定排除过滤器
*/
@ComponentScan(value = "cc.fireflyhut.study.*",
        /// 注释掉排除过滤器
        /*
        excludeFilters = {
            // 该过滤器指定为按注解过滤,过滤被Service注解的类和被Repository注解的类,加注两类注解的类将不再被扫描
            @Filter(type = FilterType.ANNOTATION, classes = {Repository.class, Service.class})
        },
        */
        includeFilters = {
                // 该过滤器指定为按注解过滤,指定被Service注解的类和被Repository注解的类,只有加注两类注解的类才能被扫描
                @Filter(type = FilterType.ANNOTATION, classes = {Repository.class, Service.class})
        },
        useDefaultFilters = false)
public class MyConfig {

    /**
     * 向容器中注册一个id未user类型为User的Bean
     * 该Bean的id默认为方法名(user)如果想指定id,需要在@Bean注解中传入value值指定id
     */
    @Bean
    public User user() {
        return new User("admin", "123456");
    }

    /**
     * 指定注册到容器中的bean的id为user111
     */
    @Bean("user111")
    public User user1() {
        return new User("admin", "123456");
    }

}

再次执行测试类测试方法
image.png
很容易发现容器中只有名为myRepository的bean和名为myService的bean了。

自定义TypeFilter

编写自定义的TypeFilter

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;

/**
 * 自定义TypeFilter
 */
public class MyTypeFilter implements TypeFilter {

    /**
     * 匹配方法
     * @param metadataReader 当前被扫描的类信息
     * @param metadataReaderFactory 任何其他的信息
     * @return 匹配结果
     * @throws IOException 抛出io异常
     */
    @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("My")) {
            return true;
        }
        return false;
    }
}

将其应用在ComponentScan注解中

import cc.fireflyhut.study.custom.MyTypeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration
/*
  value值指定扫描cc.fireflyhut.study包
  excludeFilters指定排除过滤器
*/
@ComponentScan(value = "cc.fireflyhut.study.*",
        includeFilters = {
                // 通过自定义规则过滤
                @Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
        },
        useDefaultFilters = false)
public class MyConfig {

}

测试主类

public class MyTest {

    public static void main(String[] args) {
        // 获得注解配置容器类
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);

        // 从容器中获得所有指定类型的bean的名字即id
        String[] beanNames = applicationContext.getBeanDefinitionNames();
        // 遍历打印id
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }

}

结果:
预期是只要是类名包含“My”字符就放入容器。
image.png

# Spring # Spring Framework
Spring注解学习[email protected]和@Bean
力扣12题-整数转罗马数字-贪心
  • 文章目录
  • 站点概览
优律

优律

优律的知识库

77 日志
20 分类
44 标签
E-mail Twitter Instagram
Links
  • CZLisyx - 浮生志
  • Vedfolnir
0%
© 2019 — 2023 萤火小屋——优律的博客网站
网站已勉强运行 
Halo博客系统技术支持