基本用途
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。例如:

@Configuration
public class AppConfig {

@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
}
}

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class);//加载配置类
ctx.refresh();//刷新并创建容器
MyBean myBean = ctx.getBean(MyBean.class);
// use myBean ...

注意:

@Configuration不可以是final类型;
@Configuration不可以是匿名类;
嵌套的configuration必须是静态类。
加载配置类方法
硬编码,例如ctx.register(AppConfig.class);
使用xml配置
<beans>
//这个注解用于启用ConfigurationClassPostProcessor等后置处理器,以加载以下类到容器。
<context:annotation-config/>
<bean class="com.acme.AppConfig"/>
</beans>

XmlWebApplicationContext xmlWebApplicationContext = new XmlWebApplicationContext();
xmlWebApplicationContext.setConfigLocation("abc.xml");
1
组件扫描。@Configuration本身是继承自@Component,因此也可以和正常被@Component一样被扫描到,或使用autowired。
package com.acme.app.services

@Configuration
public class AppConfig {
private final SomeBean someBean;

//这里可以通过Spring注入someBean
public AppConfig(SomeBean someBean) {
this.someBean = someBean;
}

// @Bean definition using "SomeBean"

}

要想AppConfig被扫描到,可以

@Configuration
@ComponentScan("com.acme.app.services")
public class RootConfig {
// various @Bean definitions ...
}

使用外部变量
注入Environment属性(可用于获取系统、JVM等环境变量),并配合@PropertySources注解,加载配置文件,使用@Value加载配置项。
@Configuration
@PropertySource("classpath:/com/acme/app.properties")
public class AppConfig {

@Inject Environment env;

//PropertySourcesPlaceholderConfigurer,usually enabled via XML with <context:property-placeholder/>
@Value("${bean.name}") String beanName;

@Bean
public MyBean myBean() {
return new MyBean(env.getProperty("bean.name"));
}
}

组合多个配置类
类似于xml的\标签,可以使用@Import组合多个配置类,例如:

@Configuration
public class DatabaseConfig {

@Bean
public DataSource dataSource() {
// instantiate, configure and return DataSource
}
}

@Configuration
@Import(DatabaseConfig.class)
public class AppConfig {

private final DatabaseConfig dataConfig;

public AppConfig(DatabaseConfig dataConfig) {
this.dataConfig = dataConfig;
}

@Bean
public MyBean myBean() {
// reference the dataSource() bean method
return new MyBean(dataConfig.dataSource());
}
}

//最后只需要导入一个即可
new AnnotationConfigApplicationContext(AppConfig.class);

@Configuration导入xml配置
@Configuration
@ImportResource("classpath:/com/acme/database-config.xml")
public class AppConfig {

@Inject DataSource dataSource; // from XML

@Bean
public MyBean myBean() {
// inject the XML-defined dataSource bean
return new MyBean(this.dataSource);
}
}

内部类注解
@Configuration
public class AppConfig {

@Inject DataSource dataSource;

@Bean
public MyBean myBean() {
return new MyBean(dataSource);
}

@Configuration
static class DatabaseConfig {
@Bean
DataSource dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
}
}

@Lazy懒加载
可以与@Configuration和@Bean配合使用。Spring默认不是懒加载。

@EnableXXX注解
配合@Configuration使用,包括 @EnableAsync, @EnableScheduling, @EnableTransactionManagement, @EnableAspectJAutoProxy, @EnableWebMvc。

@EnableWebMvc
常见使用方式如下所示:

@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyWebConfiguration {

}

一旦使用了该注解,则会默认加载WebMvcConfigurationSupport配置,包括:

1. HandlerMappings
1. RequestMappingHandlerMapping 用于处理url到注解controller的method映射,序号是0
2. HandlerMapping 用于处理url到view的映射,序号是1
3. BeanNameUrlHandlerMapping 用于处理url到controller的beanname映射,序号是2
4. HandlerMapping 用于处理静态资源,序号是Integer.MAX_VALUE-1
5. HandlerMapping 用于forward到default servlet,序号是Integer.MAX_VALUE

2. HandlerAdapters
1. RequestMappingHandlerAdapter 用于处理带有注解Controller的响应处理方法
2. HttpRequestHandlerAdapter 用于处理实现 HttpRequestHandler 的响应处理器
3. SimpleControllerHandlerAdapter 用于处理实现Controller接口的响应处理器

3. HandlerExceptionResolverComposite
1. ExceptionHandlerExceptionResolver 用于处理@ExceptionHandler注解
2. ResponseStatusExceptionResolver 用于处理@ResponseStatus注解
3. DefaultHandlerExceptionResolver 用于处理已知的Spring异常

4. AntPathMatcher 和 UrlPathHelper

你也可以不使用该注解,而是配置类继承WebMvcConfigurationSupport类或DelegatingWebMvcConfiguration,。或者使用@EnableWebMvc,并实现 WebMvcConfigurer接口,或 WebMvcConfigurerAdapter 适配器,例如:

@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyConfiguration extends WebMvcConfigurerAdapter {

@Override
public void addFormatters(FormatterRegistry formatterRegistry) {
formatterRegistry.addConverter(new MyConverter());
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MyHttpMessageConverter());
}

// More overridden methods ...
}

@Profile逻辑组配置
用于指定配置类加载的逻辑组(a named logical grouping),只有在组内的配置类才会被加载。该注解类似于在xml的配置,例如\。@Profile可以在配置类上,也可以在配置类的方法上。如果不配置该注解,默认是无论如何都会加载。

可以通过以下方式设置:

在JVM参数、系统环境参数或web.xml的initParam spring.profiles.active、spring.profiles.default(来自org.springframework.core.env.AbstractEnvironment) 。如果当spring.profiles.active属性被设置时,那么Spring会优先使用该属性对应值来激活Profile。当spring.profiles.active没有被设置时,那么Spring会根据spring.profiles.default属性的对应值来进行Profile进行激活。如果上面的两个属性都没有被设置,那么就不会有任务Profile被激活,只有定义在Profile之外的Bean才会被创建。
或者使用ConfigurableEnvironment.setActiveProfiles 指定需要激活的逻辑组名。
在测试类中,使用@ActiveProfiles注解指定。
@Profile("embedded", "!abc")//表示当embedded激活,abc不激活时加载本配置类
@Configuration
public class EmbeddedDatabaseConfig {

@Bean
public DataSource dataSource() {
// instantiate, configure and return embedded DataSource
}
}

@Profile("production")
@Configuration
public class ProductionDatabaseConfig {

@Bean
public DataSource dataSource() {
// instantiate, configure and return production DataSource
}
}

等同于

<beans profile="development">
<!-- 只扫描开发环境下使用的类 -->
<context:component-scan base-package="" />
<!-- 加载开发使用的配置文件 -->
<util:properties id="config" location="classpath:dev/config.properties"/>
</beans>

我们甚至可以自定义Profile注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("dev")
pubilc @interface Dev {
}

ConfigurableEnvironment
用于在没有配置项的时候,用硬编码方式指定激活逻辑组、设置默认逻辑组,或增加新的逻辑组等。

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("dev");
ctx.register(TransferServiceConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();

配置信息
最主要需要搞懂三个类PropertySource、PropertyResolver、Environment,PropertySource用于定于基本的配置数据来源,PropertyResolver用于对PropertySource进行解析,包括EL表达式(占位符替换),或进行类型转换(String->Integer等),Environment继承自PropertyResolver,这也是为何使用Environment.getProperty可以用el表达式的原因。

propertySource
propertySource
propertyResolver
propertyResolver
Environment
Environment
被使用
继承
PropertySource
加载各种配置信息。其中ComposePropertySource提供了组合PropertySource的功能,查找顺序就是注册顺序。默认提供了一个MutablePropertySources实现,我们可以调用addFirst添加到列表的开头,addLast添加到末尾,另外可以通过addBefore(propertySourceName, propertySource)或addAfter(propertySourceName, propertySource)添加到某个propertySource前面/后面;最后大家可以通过iterator迭代它,然后按照顺序获取属性。

Map<String, Object> map = new HashMap<>();
map.put("encoding", "gbk");
PropertySource propertySource1 = new MapPropertySource("map", map);
System.out.println(propertySource1.getProperty("encoding"));

ResourcePropertySource propertySource2 = new ResourcePropertySource("resource", "classpath:resources.properties"); //name, location
System.out.println(propertySource2.getProperty("encoding"));

PropertyResolver 与 Environment
Environment环境,比如JDK环境,Servlet环境,Spring环境等等;每个环境都有自己的配置数据,如System.getProperties()、System.getenv()等可以拿到JDK环境数据;ServletContext.getInitParameter()可以拿到Servlet环境配置数据等等;也就是说Spring抽象了一个Environment来表示环境配置。也可以获取或设置Profile。

MockEnvironment:模拟的环境,用于测试时使用;
StandardEnvironment:标准环境,普通Java应用时使用,会自动注册System.getProperties() 和 System.getenv()到环境;
StandardServletEnvironment:标准Servlet环境,其继承了StandardEnvironment,Web应用时使用,除了StandardEnvironment外,会自动注册ServletConfig(DispatcherServlet)、ServletContext及JNDI实例到环境;

Spring中Configuration的理解的更多相关文章

  1. Spring中IOC的理解

    Spring中IOC的理解 1.什么是IOC? (1)控制反转.把对象创建和对象间的调用过程交给Spring进行管理. (2)使用IOC的目的:为了耦合度降低. 2.IOC底层原理? (1)xml解析 ...

  2. 关于Spring中AOP的理解

    AOP简介[理解][重点] 1.AOP(Aspect Oriented Programing)面向切面/方面编程 2.AOP隶属软件工程的范畴,指导开发人员如何制作开发软件,进行结构设计 3.AOP联 ...

  3. 浅析对spring中IOC的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  4. Spring中AOP的理解

    1.AOP的概念 AOP(AspectOriented Programming,面向切面编程)指的是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下个程序动态统一添加功能的一种技术.AOP ...

  5. Spring中WebApplicationInitializer的理解

    现在JavaConfig配置方式在逐步取代xml配置方式.而WebApplicationInitializer可以看做是Web.xml的替代,它是一个接口.通过实现WebApplicationInit ...

  6. spring中的ResponseEntity理解

    参考: https://blog.csdn.net/weixin_37869477/article/details/82762976 https://blog.csdn.net/sswqzx/arti ...

  7. Spring中Bean及@Bean的理解

    Spring中Bean及@Bean的理解 Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法: 一.Bean是啥 1.Java面向对象,对象有方法和属性, ...

  8. 原创 | 我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration

    GitHub 3.7k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 3.7k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 3.7k Star 的 ...

  9. 我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration

    现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一行简单的注解就可以解决很多事情.但是,其实每一个注解背后都有很多值得学习和思考的内容.这些思考 ...

随机推荐

  1. OSPF多区域配置;骨干区域与非骨干区域;ABR边界路由器;LSA和SPF算法

    SPF:链路状态路由算法.基本用于OSPF中,但是要求路由器路由数据库足够大,因为链路状态信息包括很多内容,这也是一个缺点. OSPF是一种内部网关协议(IGP) OSPF路由协议是一种典型的链路状态 ...

  2. Spring框架中Spring配置文件中<context:annotation-config/>标签说明

    <context:annotation-config/>此标签的重要作用就是: 省去系统繁琐的注解标签,加上一个此标签,就可以在此项目程序添加“注解”的功能,使系统识别相应的注解功能!! ...

  3. RMQ(连续相同最大值)

    http://poj.org/problem?id=3368 Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submi ...

  4. python学习第十五天集合的创建和基本操作方法

    集合是python独有的数据列表,集合可以做数据分析,集合是一个无序的,唯一的的数据类型,可以确定列表的唯一性,说一下集合的创建和基本常见操作方法 1,集合的创建 s={1,2,4} 也可以用set( ...

  5. git-ssh-keygen

    ssh-keygen 先看本地是否已经有了密钥 cd ~/.ssh 该文件夹下会包含两个文件 id_rsa --私钥 id_rsa.pub --公钥 如果没有这两个文件的话就需要重新生成(有的话使用一 ...

  6. C语言获取当前时间

    #include <stdio.h> #include <time.h> void main () { time_t rawtime; struct tm * timeinfo ...

  7. EAN13条码的校验位的Excel算法

    校验位原公式: 单元格=10-RIGHT(SUM(MID($B3,{1;2;3;4;5;6;7;8;9;10;11;12},1)*{1;3;1;3;1;3;1;3;1;3;1;3})) 简化公式: 单 ...

  8. day03 for循环、字符串方法、类型转换

    01 上周内容回顾 while 条件: 循环体 例: while True: print(111) print(222) print(333) 结束循环的两种方式: 1,改变条件. 2,break. ...

  9. Sybase 修改数据库默认排序

    我新建了一个sybase数据库,想用dump文件load,可是报数据库的排序不对,就去Centrol里面修改,但是还是报错,说是字符集不存在.办法如下: 打开命令行,进入到sybase的ASE-15_ ...

  10. 【LeetCode】智商题 brainteaser(共3题)

    [292]Nim Game [319]Bulb Switcher [777]Swap Adjacent in LR String (2019年2月13日,谷歌tag) 给了两个字符串start 和en ...