跳至主要内容

Spring Boot Introduction

Spring Boot Introduction

What is Spring Boot? What the usage of it and what’s the differences between Spring Boot and Spring? In this blog, we are going to solve those questions by introducing some basic idea.

Project Dependency Structure

First, we can see the projects hierarchy from the pom dependency:

spring-boot-dependencies 
# list all dependencies of spring boot: include spring boot jar and some third party jar
	spring-boot-parent
		spring-boot-starters
		# list all starter project, which is a set of convenient dependency descriptor
			spring-boot-starter-xxx(data-elastcisearch, web, etc)
			# specific tech dependencies
	spring-boot-starter-parent
	# can include `spring-boot-starter-xxx`

So, what is starter and boot?

Boot

Boot is the project to start web application more easily with the help of:

  • Embedded tomcat or jetty in spring-boot-starter-web
  • Spring ApplicationContext etc

Starter

Starters are a set of convenient dependency descriptors, i.e. pom files or other equivalent files, that we can include in our application. we get a one-stop-shop for all the Spring and related technology that we need without having to hunt through tutorial and copy paste loads of dependency descriptors. For example, if we want to get started using Spring and Elasticsearch for searching, we can just include the spring-boot-starter-data-elasticsearch dependency in our project, and we are ready to go.

But what should be noticed is that, we had better view what the specific starter includes and understand the dependency relationship, otherwise, we will stuck when we need to customize dependency.

Auto Config

Auto-configuration is a very convenient way to reduce the work of declare beans by deducing which beans we might need based on the content of our classpath. Auto-configuration will always back away when we decided to define our own beans. And this is implemented by ConditionalOnMissingBean:

ConditionalOnMissingBean

It can be used to define a bean if the exact class (super class not match) match or name match:

Conditional that only matches when the specified bean classes and/or names are not already contained in the BeanFactory.

EnableXXX and XXX

When using some not very common features, we need to use EnableXXX to let Spring Boot know that we need this feature and customize what this feature needs:

@EnableScheduling
public class ScheduleApplication implements CommandLineRunner {

	// only autowired when enable schedule
    @Autowired
    private ScheduledAnnotationBeanPostProcessor postProcessor;

Mis

After introduce the three main parts of Spring Boot (Boot, Starter, Auto Config), we introduce some other convenient helper.

@Bean

This annotation can be used to annotate a method, which create beans in some type and name. The bean name is default the method name, and this method can also has input, which must be other beans.

Static or Not

As far as I could say, we had better to use static if we can.

The following is an example cited from document:

Special consideration must be taken for @Bean methods that return Spring BeanFactoryPostProcessor (BFPP) types. Because BFPP objects must be instantiated very early in the container lifecycle, they can interfere with processing of annotations such as @Autowired, @Value, and @PostConstruct within @Configuration classes. To avoid these lifecycle issues, mark BFPP-returning @Bean methods as static. For example:

@Bean
public static PropertySourcesPlaceholderConfigurer pspc() {
    // instantiate, configure and return pspc ...
}
   return type assignable to BeanFactoryPostProcessor.

By marking this method as static, it can be invoked without causing instantiation of its declaring @Configuration class, thus avoiding the above-mentioned lifecycle conflicts. Note however that static @Bean methods will not be enhanced for scoping and AOP semantics as mentioned above. This works out in BFPP cases, as they are not typically referenced by other @Bean methods. As a reminder, a WARN-level log message will be issued for any non-static @Bean methods having a return type assignable to BeanFactoryPostProcessor.

Properties

We can define some environment or properties of project in application.xml and/or applicatoin.yml (i.e property file & yaml file’s can be used at the same time.) to customize the auto configured beans or used in our project.

For example, setting properties of Elasticsearch:

spring.data.elasticsearch.cluster-name=searching


@ConfigurationProperties(prefix = "spring.data.elasticsearch")
public class ElasticsearchProperties {
	private String clusterName = "elasticsearch";
}

Or setting properties of rabbitmq:

spring.rabbitmq.host = 127.0.0.1
spring.rabbitmq.port = 5672

@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitProperties {
	private String host = "localhost";
}

AutoConfig and Bean

If a bean is config in Java by @Bean, settings in properties about this bean will not work. Because these properties is used with auto config, when beans is created by spring. In other word, we can not use auto config and @Bean at the same time.

Profile Specfic

java -jar myproject.jar --spring.profiles.active=dev,hsqldb

In addition to application.properties files, profile-specific properties can also be defined using the naming convention application-{profile}.properties.

Debug

Debug Model

The default log configuration will echo messages to the console as they are written. By default ERROR, WARN and INFO level messages are logged. we can also enable a “debug” mode by starting our application with a --debug flag.

$ java -jar myapp.jar --debug

Or, we can also specify debug=true in our application.properties.

The third way, used in development:

SpringApplication.run(SearchdemoApplication.class, "--debug").close();

Enabling the debug mode does not configure our application to log all messages with DEBUG level ( the list of enabled logger can be found LoggingApplicationListener ).

Log

By default, If we use the Starters, Logback will be used for logging.

All the supported logging systems can have the logger levels set in the Spring Environment (so for example in application.properties) using logging.level.*=LEVEL where LEVEL is one of TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF.

The logging system is initialized early in the application lifecycle (i.e. before the processing of annotation) and as such logging properties will not be found in property files loaded via @PropertySource annotations.

Logback Sample Output
2017-06-06 16:56:11.360  WARN 77933 --- [           main] org.elasticsearch.client.transport       : [Madame Menace] node {#transport#-1}{192.168.1.100}{192.168.1.100:9300} not part of the cluster Cluster [elasticsearch], ignoring...

Written with StackEdit.

评论

此博客中的热门博文

Spring Boot: Customize Environment

Spring Boot: Customize Environment Environment variable is a very commonly used feature in daily programming: used in init script used in startup configuration used by logging etc In Spring Boot, all environment variables are a part of properties in Spring context and managed by Environment abstraction. Because Spring Boot can handle the parse of configuration files, when we want to implement a project which uses yml file as a separate config file, we choose the Spring Boot. The following is the problems we met when we implementing the parse of yml file and it is recorded for future reader. Bind to Class Property values can be injected directly into your beans using the @Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects via @ConfigurationProperties. As the document says, there exists three ways to access properties in *.properties or *.yml : @Value : access single value Environment : can access multi

Elasticsearch: Join and SubQuery

Elasticsearch: Join and SubQuery Tony was bothered by the recent change of search engine requirement: they want the functionality of SQL-like join in Elasticsearch! “They are crazy! How can they think like that. Didn’t they understand that Elasticsearch is kind-of NoSQL 1 in which every index should be independent and self-contained? In this way, every index can work independently and scale as they like without considering other indexes, so the performance can boost. Following this design principle, Elasticsearch has little related supports.” Tony thought, after listening their requirements. Leader notice tony’s unwillingness and said, “Maybe it is hard to do, but the requirement is reasonable. We need to search person by his friends, didn’t we? What’s more, the harder to implement, the more you can learn from it, right?” Tony thought leader’s word does make sense so he set out to do the related implementations Application-Side Join “The first implementation

Implement isdigit

It is seems very easy to implement c library function isdigit , but for a library code, performance is very important. So we will try to implement it and make it faster. Function So, first we make it right. int isdigit ( char c) { return c >= '0' && c <= '9' ; } Improvements One – Macro When it comes to performance for c code, macro can always be tried. #define isdigit (c) c >= '0' && c <= '9' Two – Table Upper version use two comparison and one logical operation, but we can do better with more space: # define isdigit(c) table[c] This works and faster, but somewhat wasteful. We need only one bit to represent true or false, but we use a int. So what to do? There are many similar functions like isalpha(), isupper ... in c header file, so we can combine them into one int and get result by table[c]&SOME_BIT , which is what source do. Source code of ctype.h : # define _ISbit(bit) (1 << (