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 ...

注意

  1. @Configuration不可以是final类型;
  2. @Configuration不可以是匿名类;
  3. 嵌套的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");
  • 组件扫描。@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 ...
   }

参考:

http://www.cnblogs.com/xd502djj/archive/2012/09/24/2700490.html spring mvc 异常统一处理方式
http://www.cnblogs.com/hupengcool/p/4586910.html SpringMVC 异常处理
http://www.jianshu.com/p/cbcf78360308 Java Web技术经验总结(九)

@Profile逻辑组配置

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

可以通过以下方式设置:

  1. 在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才会被创建。
  2. 或者使用ConfigurableEnvironment.setActiveProfiles 指定需要激活的逻辑组名。
  3. 在测试类中,使用@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 {
}

参考:

http://www.jianshu.com/p/948c303b2253 详解Spring中的Profile
http://zilongsky-gmail-com.iteye.com/blog/2032001 Maven 整合 spring profile实现多环境自动切换
http://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/ Spring 3.1 M1: Introducing @Profile

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表达式的原因。

Created with Raphaël 2.1.0 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"));

这里写图片描述

参考:

http://sishuok.com/forum/blogPost/list/7936.html Spring3.1新属性管理API:PropertySource、Environment、Profile

PropertyResolver 与 Environment

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

这里写图片描述

  1. MockEnvironment:模拟的环境,用于测试时使用;
  2. StandardEnvironment:标准环境,普通Java应用时使用,会自动注册System.getProperties() 和 System.getenv()到环境;
  3. StandardServletEnvironment:标准Servlet环境,其继承了StandardEnvironment,Web应用时使用,除了StandardEnvironment外,会自动注册ServletConfig(DispatcherServlet)、ServletContext及JNDI实例到环境;
  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值