zoukankan      html  css  js  c++  java
  • 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实例到环境;

  • 相关阅读:
    unity 反编译 step2 dll -->reflector
    unity 反编译 step1 disUnity
    rpg
    cmake使用
    linux mysqld的启动过程
    unity内存加载和释放
    Linux下MySql数据库常用操作
    MySQL主从复制与读写分离(非原创,谢绝膜拜)
    linux下IPTABLES配置详解
    linux下查看端口的占用情况
  • 原文地址:https://www.cnblogs.com/yhtboke/p/10215867.html
Copyright © 2011-2022 走看看