Spring boot自动配置

1、从源码角度看spring boot 自动配置

SpringApplication application = new SpringApplication(HelloApplication.class);

这个方法调用的是

public SpringApplication(Object... sources) {
        initialize(sources);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
        if (sources != null && sources.length > 0) {
            this.sources.addAll(Arrays.asList(sources));
        }
        this.webEnvironment = deduceWebEnvironment();
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
}

getSpringFactoriesInstances方法最终最重要的调用是:

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        try {
            Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            List<String> result = new ArrayList<String>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                String factoryClassNames = properties.getProperty(factoryClassName);
                result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
                    "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }

而 FACTORIES_RESOURCE_LOCATION=META-INF/spring.factories
这个其实就是一些自动配置类,如果满足条件就创建配置类,加载配置。这个其实就是spring boot根据jar包自动配置的原理。

2、模拟自动配置

2.1属性类

package cn.itcast.springboot.demo.auto;

import org.springframework.stereotype.Component;

/**
 * 创建真正的bean需要的属性类
 * 2018年4月15日
 *
 */
@Component
public class HelloProperties {

  private String msg="default";//现在我们在配置文件写hello.msg=world,因为简单就不再展示;如果那么默认为default.

  public String getMsg() {
      return msg;
  }

  public void setMsg(String msg) {
      this.msg = msg;
  }
}

2.2 spring需要管理的bean

package cn.itcast.springboot.demo.auto;


public class HelloService {

    private String msg = "service";//如果自动配置没有读入成功,那么为默认值

    public String say() {
        return "hello " + msg;
    }//为我们服务的方法

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

2.4 模拟spring boot的自动配置类
它主要负责把HelloProperties 的属性注入到HelloService 中去

package cn.itcast.springboot.demo.auto;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration //配置类
@ConditionalOnClass(HelloService.class)//当类路径存在这个类时才会加载这个配置类
public class HelloAutoConfiguration {

    @Autowired
    private HelloProperties helloProperties;

    @Bean
    @ConditionalOnMissingBean(HelloService.class)//如果没有我们的自定义Bean那么才会自动配置一个新的Bean
    public HelloService auto(){
        HelloService helloService =new HelloService();
        helloService.setMsg(helloProperties.getMsg());
        return helloService;
    }

}

通过上面三步在spring容器中就创建了 HelloService ,并且把属性都自动配置好了

阅读更多
个人分类: spring boot
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭