主配置类@Configuration、组件扫描@ComponentScan

2023-12-31 14:08

本文主要是介绍主配置类@Configuration、组件扫描@ComponentScan,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 主配置
    • xml文件配置的方式
    • 注解的方式:主配置类@Configuration
    • @Configuration源码
  • 组件扫描:@ComponentScan
    • XML配置文件方式
    • @ComponentScan注解方式
    • @ComponentScan源码:
    • includeFilters指定规则扫描组件
    • 过滤规则
    • 自定义匹配规则FilterType.CUSTOM
  • 总结
    • 注解用法
    • 获取IoC容器的方法:

主配置

xml文件配置的方式

先按照我们以前配置的方式来使用Spring,给出主配置XML:
首先有一个Person类:

public class Person {private String name;private Integer 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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}

主配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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="com.ldc.bean.Person"><property name="age" value="18"></property><property name="name" value="张三"></property></bean>
</beans>

测试

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

输出结果为:

Person{name=‘张三’, age=18}

注解的方式:主配置类@Configuration

首先我们先写一个配置类:其作用与xml配置文件相同,均是给Spring做出一些配置和导入一些组件

/***  配置类就等同以前的配置文件*/
@Configuration //告诉Spring这是一个配置类
public class MainConfig {//相当于xml配置文件中的<bean>标签,告诉容器注册一个bean//之前xml文件中<bean>标签有bean的class类型,那么现在注解方式的类型当然也就是返回值的类型//之前xml文件中<bean>标签有bean的id,现在注解的方式默认用的是方法名来作为bean的id@Beanpublic Person person() {return new Person("lisi",20);}}

测试:

public class MainTest {public static void main(String[]args){/*** 这里是new了一个AnnotationConfigApplicationContext对象,以前new的ClassPathXmlApplicationContext对象* 的构造函数里面传的是配置文件的位置,而现在AnnotationConfigApplicationContext对象的构造函数里面传的是* 配置类的类型*/ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);Person person = applicationContext.getBean(Person.class);System.out.println(person);}
}

输出结果为:

Person{name=‘张三’, age=18}

@Configuration源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {/*** Explicitly specify the name of the Spring bean definition associated* with this Configuration class. If left unspecified (the common case),* a bean name will be automatically generated.* <p>The custom name applies only if the Configuration class is picked up via* component scanning or supplied directly to a {@link AnnotationConfigApplicationContext}.* If the Configuration class is registered as a traditional XML bean definition,* the name/id of the bean element will take precedence.* @return the specified bean name, if any* @see org.springframework.beans.factory.support.DefaultBeanNameGenerator*/String value() default "";}

从@Configuration 这个注解点进去就可以发现这个注解上也标注了 @Component 的这个注解,说明被他标注的主配置类也纳入到IOC容器中作为一个组件

组件扫描:@ComponentScan

作用:自动扫描注册组件并可以指定特定的扫描规则

XML配置文件方式

在xml文件配置的方式,我们可以这样来进行配置:

    <!-- 包扫描、只要标注了@Controller@Service@Repository@Component 均可以将其作为组件扫描进来--><context:component-scan base-package="com.ldc"/>

@ComponentScan注解方式

以前是在xml配置文件里面写包扫描,现在我们可以在配置类里面写包扫描:

/*** 配置类就等同以前的配置文件*/
@Configuration //告诉Spring这是一个配置类
@ComponentScan(value = "com.ldc")//相当于是xml配置文件里面的<context:component-scan base-package="com.ldc"/>
public class MainConfig {//相当于xml配置文件中的<bean>标签,告诉容器注册一个bean//之前xml文件中<bean>标签有bean的class类型,那么现在注解方式的类型当然也就是返回值的类型//之前xml文件中<bean>标签有bean的id,现在注解的方式默认用的是方法名来作为bean的id@Bean(value = "person")//通过这个value属性可以指定bean在IOC容器的idpublic Person person01() {return new Person("lisi",20);}}

测试:
我们创建BookController、BookService、BookDao这几个类,分别添加了@Controller、@Service、@Repository注解:

@Controller
public class BookController {
}
@Service
public class BookService {
}
    @Testpublic void test01() {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);}}

结果如下:除开IOC容器自己要装配的一些组件外,还有是我们自己装配的组件

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

从上面的测试结果我们可以发现主配置类 MainConfig 也是IOC容器里面的组件,也被纳入了IOC容器的管理。

@ComponentScan源码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};Class<?>[] basePackageClasses() default {};Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;String resourcePattern() default "**/*.class";boolean useDefaultFilters() default true;ComponentScan.Filter[] includeFilters() default {};//这个是要排除的规则:是按注解来进行排除还是按照类来进行排除还是按照正则表达式来来进行排除ComponentScan.Filter[] excludeFilters() default {};boolean lazyInit() default false;@Retention(RetentionPolicy.RUNTIME)@Target({})public @interface Filter {FilterType type() default FilterType.ANNOTATION;@AliasFor("classes")Class<?>[] value() default {};@AliasFor("value")Class<?>[] classes() default {};String[] pattern() default {};}
}

这个时候,我们就可以这样来配置:

@Configuration
@ComponentScan(value = "com.ldc",excludeFilters = {//这里面是一个@Filter注解数组,FilterType.ANNOTATION表示的排除的规则 :按照注解的方式来进行排除//classes = {Controller.class,Service.class}表示的是标有这些注解的类给排除掉@Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})
})
public class MainConfig {@Bean(value = "person")public Person person01() {return new Person("lisi",20);}}

includeFilters指定规则扫描组件

我们也可以来配置includeFilters:指定在扫描的时候,只需要包含哪些组件
在用xml文件配置的方式来进行配置的时候,还要禁用掉默认的配置规则,只包含哪些组件的配置才能生效

<context:component-scan base-package=“com.ldc” use-default-filters=false/>

在这里插入图片描述
书写案例:

@Configuration
//excludeFilters = Filter[];指定在扫描的时候按照什么规则来排除脑哪些组件
//includeFilters = Filter[];指定在扫描的时候,只需要包含哪些组件
@ComponentScan(value = "com.ldc",includeFilters = {//这里面是一个@Filter注解数组,FilterType.ANNOTATION表示的排除的规则 :按照注解的方式来进行排除//classes = {Controller.class}表示的是标有这些注解的类给纳入到IOC容器中@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
},useDefaultFilters = false)
public class MainConfig {@Bean(value = "person")public Person person01() {return new Person("lisi",20);}}

过滤规则

public enum FilterType {ANNOTATION,ASSIGNABLE_TYPE,ASPECTJ,REGEX,CUSTOM;private FilterType() {}
}

书写案例

@Configuration
//excludeFilters = Filter[];指定在扫描的时候按照什么规则来排除脑哪些组件
//includeFilters = Filter[];指定在扫描的时候,只需要包含哪些组件
@ComponentScans(value = {@ComponentScan(value = "com.ldc",includeFilters = {//这里面是一个@Filter注解数组,FilterType.ANNOTATION表示的排除的规则 :按照注解的方式来进行匹配//classes = {Controller.class}表示的是标有这些注解的类给纳入到IOC容器中// FilterType.ANNOTATION 按照注解来进行匹配// FilterType.ASSIGNABLE_TYPE 按照给定的类型来进行匹配@Filter(type = FilterType.ANNOTATION, classes = {Controller.class}),//按照给定的类型来进行匹配@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookService.class})},useDefaultFilters = false)
})public class MainConfig {@Bean(value = "person")public Person person01() {return new Person("lisi",20);}}

下面的这两种是我们最常用的匹配规则:

FilterType.ANNOTATION 按照注解来进行匹配FilterType.ASSIGNABLE_TYPE
按照给定的类型来进行匹配

自定义匹配规则FilterType.CUSTOM

我们可以自己来写一个匹配规则的类:MyTypeFilter,这个类要实现TypeFilter这个接口

public class MyTypeFilter implements TypeFilter {/**** @param metadataReader  the metadata reader for the target class 读取到当前正在扫描的类的信息* @param metadataReaderFactory a factory for obtaining metadata readers 可以获取到其他任何类的信息* @return* @throws IOException*/@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {//获取到当前类注解的信息AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();//获取当前类的资源的信息(比如类的路径)Resource resource = metadataReader.getResource();//获取到当前正在扫描的类的信息ClassMetadata classMetadata = metadataReader.getClassMetadata();String className = classMetadata.getClassName();System.out.println("通过自定义的匹配规则--->"+className);return false;}
}

这个时候,我们就可以这样来用了:使用FilterType.CUSTOM

@Configuration
//excludeFilters = Filter[];指定在扫描的时候按照什么规则来排除脑哪些组件
//includeFilters = Filter[];指定在扫描的时候,只需要包含哪些组件
@ComponentScans(value = {@ComponentScan(value = "com.ldc",includeFilters = {//自定义匹配的规则@Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})},useDefaultFilters = false)
})public class MainConfig {@Bean(value = "person")public Person person01() {return new Person("lisi",20);}}

总结

注解用法

//配置类==配置文件
@Configuration //告诉Spring这是一个配置类@ComponentScans(
value = {
@ComponentScan(value="com.atguigu",includeFilters = {
/* @Filter(type=FilterType.ANNOTATION,classes={Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}),*/
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class})
},useDefaultFilters = false)
}
)
//@ComponentScan value:指定要扫描的包
//excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件
//includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
//FilterType.ANNOTATION:按照注解
//FilterType.ASSIGNABLE_TYPE:按照给定的类型;
//FilterType.ASPECTJ:使用ASPECTJ表达式
//FilterType.REGEX:使用正则指定
//FilterType.CUSTOM:使用自定义规则
public class MainConfig {//给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
}}

获取IoC容器的方法:

//获取xml配置文件时的IOC容器
//     ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//    Person bean = (Person) applicationContext.getBean("person");
//    System.out.println(bean);
获注解配置时的IOC容器ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);Person bean = applicationContext.getBean(Person.class);System.out.println(bean);

这篇关于主配置类@Configuration、组件扫描@ComponentScan的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/556258

相关文章

mybatis映射器配置小结

《mybatis映射器配置小结》本文详解MyBatis映射器配置,重点讲解字段映射的三种解决方案(别名、自动驼峰映射、resultMap),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定... 目录select中字段的映射问题使用SQL语句中的别名功能使用mapUnderscoreToCame

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

MySQL8 密码强度评估与配置详解

《MySQL8密码强度评估与配置详解》MySQL8默认启用密码强度插件,实施MEDIUM策略(长度8、含数字/字母/特殊字符),支持动态调整与配置文件设置,推荐使用STRONG策略并定期更新密码以提... 目录一、mysql 8 密码强度评估机制1.核心插件:validate_password2.密码策略级

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

QT Creator配置Kit的实现示例

《QTCreator配置Kit的实现示例》本文主要介绍了使用Qt5.12.12与VS2022时,因MSVC编译器版本不匹配及WindowsSDK缺失导致配置错误的问题解决,感兴趣的可以了解一下... 目录0、背景:qt5.12.12+vs2022一、症状:二、原因:(可以跳过,直奔后面的解决方法)三、解决方

SpringBoot路径映射配置的实现步骤

《SpringBoot路径映射配置的实现步骤》本文介绍了如何在SpringBoot项目中配置路径映射,使得除static目录外的资源可被访问,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一... 目录SpringBoot路径映射补:springboot 配置虚拟路径映射 @RequestMapp