Spring中Configuration的理解
基本用途
从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的理解的更多相关文章
- Spring中IOC的理解
Spring中IOC的理解 1.什么是IOC? (1)控制反转.把对象创建和对象间的调用过程交给Spring进行管理. (2)使用IOC的目的:为了耦合度降低. 2.IOC底层原理? (1)xml解析 ...
- 关于Spring中AOP的理解
AOP简介[理解][重点] 1.AOP(Aspect Oriented Programing)面向切面/方面编程 2.AOP隶属软件工程的范畴,指导开发人员如何制作开发软件,进行结构设计 3.AOP联 ...
- 浅析对spring中IOC的理解
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...
- Spring中AOP的理解
1.AOP的概念 AOP(AspectOriented Programming,面向切面编程)指的是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下个程序动态统一添加功能的一种技术.AOP ...
- Spring中WebApplicationInitializer的理解
现在JavaConfig配置方式在逐步取代xml配置方式.而WebApplicationInitializer可以看做是Web.xml的替代,它是一个接口.通过实现WebApplicationInit ...
- spring中的ResponseEntity理解
参考: https://blog.csdn.net/weixin_37869477/article/details/82762976 https://blog.csdn.net/sswqzx/arti ...
- Spring中Bean及@Bean的理解
Spring中Bean及@Bean的理解 Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法: 一.Bean是啥 1.Java面向对象,对象有方法和属性, ...
- 原创 | 我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration
GitHub 3.7k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 3.7k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 3.7k Star 的 ...
- 我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration
现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一行简单的注解就可以解决很多事情.但是,其实每一个注解背后都有很多值得学习和思考的内容.这些思考 ...
随机推荐
- Spring学习(二)--装配Bean
一.Spring装配机制 Spring提供了三种主要的装配机制: 1.在XML中进行显示配置 2.在Java中进行显示配置 3.隐式的bean发现机制和自动装配--自动化装配bean Spring可以 ...
- mybatis报错:org.apache.ibatis.builder.BuilderException:Encountered " "shr" "shr " " at line 1,column 1
程序报错如下: 解决:变量名冲突 表字段‘审核人’简称为shr,与mybatis的OGNL表达式发生冲突. 解决方法:修改冲突的变量名即可. 总结了一下变量命名可能发生冲突的变量集合: bor(字符| ...
- 利用Spring实现Hello World
因为最近要做Java Web方面的开发,所以,就像使用Spring来实现一个以前学其他程序时首先做的一个示例"Hello World!"练练手,之前用很多中语言实现过hello w ...
- java_第一年_JavaWeb(5)
HttpServletRequest对象 通过HttpServletRequest对象可获取客户端在访问服务器时,请求的所有信息 获取客户机的信息 getRequestURL:返回客户端发出请求时的完 ...
- C#设计模式:桥接模式(Bridge Pattern)
一,桥接模式,直接上代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...
- 关于手机端在同一个Grid中使用不同的布局展现即Layout的使用
标题可能说的不是很清楚,我举个栗子好了,现在你正在写手机端的一个审批模块,这个模块要求能够展示所有待审批的信息 比如出差申请,请假申请,加班申请,以及报销申请 那么我的思路有两个 1:建立一个Tab页 ...
- route - 显示 / 操作IP选路表
总览 SYNOPSIS route [-CFvnee] route [-v] [-A family] add [-net|-host] target [netmask Nm] [gw Gw] [met ...
- Windows server 2012/2016系统安装zabbix3.2客户端
一. 上传zabbix客户端文件 将zabbix_agents_3.2.0.win.zip文件上传至服务器的指定路径. 二. 解压并修改相关信息 解压已上传的客户端文件,在co ...
- python断言语句assert
断言语句的格式 assert test, [msg] test是一个表达式,表达式求值为Fals时引发AssertionError异常,msg是可选的异常消息. def test_assert(a): ...
- Redis和Ehcached的区别
Redis 属于独立的运行程序,需要单独安装后,使用JAVA中的Jedis来操纵.因为它是独立,所以如果你写个单元测试程序,放一些数据在Redis中,然后又写一个程序去拿数据,那么是可以拿到这个数据的 ...