spring零配置省略无关配置

在看到其他的代码中没有使用配置文件,只是使用了一个简单的属性文件,却把原来配置注册bean的代码全部给去除了,当我看到这里时我就很纳闷这是怎么做到的呢,后来经过查找发现了其中的奥秘。这些时在spring4.0以后才具有的功能,那么我们就来看看是什么原理吧:

WebApplicationInitializer 代替web.xml的配置

在Servlet 3.0+环境中实现的接口,以便以ServletContext`编程方式进行配置 -与传统的web.xml基于方法的方法相反(或可能与之结合)。会自动检测SPI的实现SpringServletContainerInitializer,它本身会被任何Servlet 3.0容器自动引导

大部分构建Web应用程序的Spring用户都需要注册Spring的DispatcherServlet。作为参考,通常在WEB-INF / web.xml中执行以下操作:

<servlet> 
   <servlet-name> dispatcher </ servlet-name> 
   <servlet-class> 
     org.springframework.web.servlet.DispatcherServlet 
   </ servlet-class> 
   <init-param> 
     <param-name> contextConfigLocation </ param-名称> 
     <param-value> /WEB-INF/spring/dispatcher-config.xml </ param-value> 
   </ init-param> 
   <load-on-startup> 1 </ load-on-startup> 
 </ servlet > 

 <servlet-mapping> 
   <servlet-name>dispatcher</ servlet-name> 
   <url-pattern> / </ url-pattern> 
 </ servlet-mapping>

// java代码代替上面操作:
public class MyWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
      XmlWebApplicationContext appContext = new XmlWebApplicationContext();
      appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

      ServletRegistration.Dynamic dispatcher =
        container.addServlet("dispatcher", new DispatcherServlet(appContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");
    }

 }

WebApplicationInitializer非常适合与Spring的基于代码的 @Configuration类一起使用但是以下示例演示了重构,以使用Spring AnnotationConfigWebApplicationContext代替XmlWebApplicationContext和用户定义的@Configuration类AppConfig, DispatcherConfig而不是Spring XML文件。此示例还超出了上面的示例,以演示“ root”应用程序上下文的典型配置和的注册ContextLoaderListener:

public class MyWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
      // Create the 'root' Spring application context
      // 请看 AbstractAnnotationConfigDispatcherServletInitializer
      AnnotationConfigWebApplicationContext rootContext =
        new AnnotationConfigWebApplicationContext();
      rootContext.register(AppConfig.class);

      // Manage the lifecycle of the root application context
      container.addListener(new ContextLoaderListener(rootContext));
      // 加载配置文件
      ResourcePropertySource props;
		try {
			props = new ResourcePropertySource("classpath:service.properties");
		} catch (IOException ex) {
			log.error("could not load properties file to use for environment configuration", ex);
			throw new ServletException(ex);
		}
	  // Create the dispatcher servlet's Spring application context
      AnnotationConfigWebApplicationContext dispatcherContext =
        new AnnotationConfigWebApplicationContext();
      dispatcherContext.register(DispatcherConfig.class)
        
      // Register and map the dispatcher servlet
      ServletRegistration.Dynamic dispatcher =
        container.addServlet("dispatcher", new DispatcherServlet(rootContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");
    }

 }

系统WebApplicationInitializer会自动检测到实现 -因此您可以随意将其打包到应用程序中

AnnotationConfigWebApplicationContext rootContext =new AnnotationConfigWebApplicationContext();

这里为何这样使用因为在AbstractAnnotationConfigDispatcherServletInitializer类中有这样的使用:

protected WebApplicationContext createRootApplicationContext() {
    Class<?>[] configClasses = this.getRootConfigClasses();
    if (!ObjectUtils.isEmpty(configClasses)) {
        AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
        rootAppContext.register(configClasses);
        return rootAppContext;
    } else {
        return null;
    }
}

protected WebApplicationContext createServletApplicationContext() {
    AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
    Class<?>[] configClasses = this.getServletConfigClasses();
    if (!ObjectUtils.isEmpty(configClasses)) {
        servletAppContext.register(configClasses);
    }

    return servletAppContext;
}

Environment接口

API解读:

表示当前应用程序正在其中运行的环境的接口。 为应用程序环境的两个关键方面建模:配置文件和属性。 与属性访问有关的方法通过PropertyResolver超级接口公开。

用来表示整个应用运行时的环境,为了更形象地理解Environment,你可以把Spring应用的运行时简单地想象成两个部分:一个是Spring应用本身,一个是Spring应用所处的环境。

Environment在容器中是一个抽象的集合,是指应用环境的2个方面:profiles和properties。

package org.springframework.core.env;

public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();

    String[] getDefaultProfiles();

    /** @deprecated */
    @Deprecated
    boolean acceptsProfiles(String... var1);

    boolean acceptsProfiles(Profiles var1);
}

1. Profile
  profile配置是一个被命名的、bean定义的逻辑组,这些bean只有在给定的profile配置激活时才会注册到容器。不管是XML还是注解,Beans都有可能指派给profile配置。Environment环境对象的作用,对于profiles配置来说,它能决定当前激活的是哪个profile配置,和哪个profile是默认。

  • 一个profile就是一组Bean定义的逻辑分组。
  • 这个分组,也就 这个profile,被赋予一个命名,就是这个profile名字。
  • 只有当一个profile处于active状态时,它对应的逻辑上组织在一起的这些Bean定义才会被注册到容器中。
  • Bean添加到profile可以通过XML定义方式或才annotation注解方式。
  • Environment对于profile所扮演的角色是用来指定哪些profile是当前活跃的缺省。

2. Properties

properties属性可能来源于properties文件、JVM properties、system环境变量、JNDI、servlet context parameters上下文参数、专门的properties对象,Maps等等。Environment对象的作用,对于properties来说,是提供给用户方便的服务接口、方便撰写配置、方便解析配置。

  • 配置属性源。
  • 从属性源中获取属性。
    容器(ApplicationContext)所管理的bean如果想直接使用Environment对象访问profile状态或者获取属性,可以有两种方式
    (1)实现EnvironmentAware接口。
    (2)@Inject或者@Autowired一个Environment对象。
    绝大数情况下,bean都不需要直接访问Environment对象,而是通过类似@Value注解的方式把属性值注入进来。

使用:

application.properties

#DataSource
ds.driver.classname=com.microsoft.sqlserver.jdbc.SQLServerDriver
ds.url=
ds.username=
ds.password=

加载配置的类:

@Configuration
@EnableWebMvc
@PropertySource("classpath:service.properties")
@EnableTransactionManagement
public class MVCConfig extends WebMvcConfigurerAdapter {
    @Autowired
    Environment env;
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

在webAppinitializer注册:

public class WebAppInitializer implements WebApplicationInitializer {
	private static final Logger log = LoggerFactory.getLogger(WebAppInitializer.class);

	@Override
	public void onStartup(ServletContext container) throws ServletException {
		log.info("starting web application initialization");

		// Create the 'root' Spring application context
		AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
		rootContext.register(MVCConfig.class);

		// Manage the lifecycle of the root application context
		container.addListener(new ContextLoaderListener(rootContext));
		ResourcePropertySource props;
		try {
			props = new ResourcePropertySource("classpath:service.properties");
		} catch (IOException ex) {
			log.error("could not load properties file to use for environment configuration", ex);
			throw new ServletException(ex);
		}
		log.info("web application initialization properties:" + props.getSource());

		// Register and map the dispatcher servlet
		ServletRegistration.Dynamic dispatcher = container.addServlet(
				"dispatcher", new DispatcherServlet(rootContext));
		dispatcher.setLoadOnStartup(1);
		dispatcher.addMapping("/");

        // Register filter to allow cross-domain requests
        //http://stackoverflow.com/questions/21864147/access-control-allow-origin-error-mvc-spring-zepto-post
        FilterRegistration.Dynamic filterRegistration=container.addFilter("filterRegistration",new SimpleCORSFilter());
        filterRegistration.setAsyncSupported(true);
        filterRegistration.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");

    }
}




package com.kayleoi.spring.data.config;

import com.jolbox.bonecp.BoneCPDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;

/**
 * 配置DATASOURCE
 这里需要配置加载@PropertySource获取resource下面的资源
 */
@Configuration
@PropertySource("classpath:application.properties")
public class DatasourceConfig {
    /***
     * Spring应用的运行时简单地想象成两个部分:一个是Spring应用本身,一个是Spring应用所处的环境。
     * Environment在容器中是一个抽象的集合,是指应用环境的2个方面:profiles和properties 就像源碼中書寫的那樣
     * String[] getActiveProfiles(); 激活的
     * String[] getDefaultProfiles(); 默认的
     */
    @Autowired
    Environment env;

    @Bean(name = "sqlServerDataSource")
    public DataSource sqlServerDataSource() {
        // BoneCP是一个快速,开源的数据库连接池。帮你管理数据连接让你的应用程序能更快速地访问数据库。
        //比C3P0/DBCP连接池快25倍。
        BoneCPDataSource ds = new BoneCPDataSource();
        ds.setDriverClass(env.getProperty("ds.driver.classname"));
        ds.setJdbcUrl(env.getProperty("ds.url"));
        ds.setUsername(env.getProperty("ds.username"));
        ds.setPassword(env.getProperty("ds.password"));
        ds.setIdleConnectionTestPeriodInMinutes(240);
        ds.setIdleMaxAgeInMinutes(60);
        ds.setMaxConnectionsPerPartition(40);
        ds.setMinConnectionsPerPartition(5);
        ds.setPartitionCount(3);
        ds.setAcquireIncrement(10);
        ds.setStatementsCacheSize(100);
        return ds;
    }
}

看了以上的代码我想已经和明了了吧为何能够这样使用,其实都是源于spring4.0以后的底层的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay三石 [Alay Kay]

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值