spring-cloud其他文章:
我们有必要花时间了解spring boot吗?
spring boot集成ActiveMQ
spring-cloud中eureka进行服务治理
概述
spring boot系列(第一篇):我们有必要花时间了解spring boot吗?
spring boot好用,原因在于省去了很多繁杂的配置。一般开发服务端项目需要的服务、数据库、事务、缓存、消息、作业、访问控制,这些模块的基础配置,spring boot都给我们配置好了。
需要哪个模块,我们要做可能就是简单的几项操作:添加对应的starter依赖;在application.properties文件添加url、端口、线程数、队列名称等属性值;添加@Enablexxx注解。
spring boot流行的原因也是在于它的简单、快速,恰好贴合了当前主流的敏捷、快速迭代的需求,给微服务化带来了很多便利。
spring boot的优点不仅仅是自动化配置,还有它的actuator提供的生产环境运维支持,打包成单个jar支持,上云支持。这些内置的支持,让java服务开发变得简单、快速、专业、易于维护。
注解orXML?
spring boot官方是主张完全用注解替代XML的。那么实际生产环境下,我们该用注解还是该用XML,哪里用注解,哪里用XML?
在stackoverflow上有一个讨论,可以看这里.
大意是说,应该结合使用annotation和XML,但遇到依赖注入的类时,被依赖的对象应该使用XML配置。这样,当需要修改实现类的时候,能够不修改代码、不重新打包完成更换。
对于生产环境,一般来说很少直接线上切换不同的实现类,换也是线下随着某一个版本的发布,完成替换。
有一点需要注意的是,对于上述提到的被依赖接口的实现类最好在单独的位置去注解,不要直接在类上注解@Component、@Repositry、@Service。建议,当一个类的实例被其他类依赖时,在一个@Configuration注解的类里面,用@Bean去注解需要实例化的类,@Configuration和@Bean是spring 3.0之后开始支持的一组新注解,从而可以支持完全无XML配置。如下形式:
package com.dangdang.cart_test.configuration.web;
import org.apache.catalina.filters.RemoteIpFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfiguration {
@Bean
public RemoteIpFilter remoteIpFilter() {
return new RemoteIpFilter();
}
@Bean
public IBookService bookService(){
return new MyBookService();
}
}
而不要直接在实现类上注解,不要像这样:
package com.dangdang.cart_test.configuration.web;
import org.springframework.stereotype.Service;
@Service
public class MyBookService implements IBookService{
}
相对于spring来说,spring boot要年轻不少。现实情况下,公司的项目很多配置都是XML配置的,这时候估计绝大多数人不会想着全部改成Annotation配置的。
对于这种情况,可以沿用XML配置,也可以对新的类用Annotation注解。Annotation和XML同时存在。
spring boot的自动注解做了什么
spring mvc项目最基础的配置需要
看一下常规的spring mvc 项目,需要web.xml配置DispatcherServlet、CharacterEncodingFilter、ContextLoaderListener:
<!-- 指定bean 容器上下文配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/**/*.xml,classpath:*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring MVC 前端控制器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/appconfig/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
还需要在spring mvc上下文配置文件中,配置MethodHandler、ViewResolver:
<!-- 定义跳转的文件的前后缀 ,视图模式配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
spring boot mvc项目配置需要
pom.xml引入starter-web的jar包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
application.properties中配置viewresolver的属性:
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
spring boot做了什么
1.自动创建常规的配置项DispatcherServlet、CharacterEncodingFilter、ContextLoaderListener、viewresolver;
2.需要配置的属性,统一在properties文件里面以spring.mvc.xxx格式的属性名配置;
自动注解实现
spring boot为每一个支持的技术(quartz、cache、batch、activemq)都提供了一个starter。引入的一个starter,就对应的引入了这项技术依赖的所有jar文件。
1.比如quzrtz的starter:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</dependency>
</dependencies>
2.每一个技术还对应了一个autoconfigure,用来当满足某个条件时(一般是某个类存在 && 某个对象不存在),自动实例化需要的对象,比如:
@Configuration
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class,
PlatformTransactionManager.class })
@EnableConfigurationProperties(QuartzProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
public class QuartzAutoConfiguration {
//省略细节的初始化代码
}
这里的@ConditionalOnClass,指定当Scheduler.class, SchedulerFactoryBean.class,PlatformTransactionManager.class (都是quartz的初始化需要的类)都存在时,执行初始化。
@AutoConfigureAfter指定,如果存在DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class配置的话,先执行他们内部的配置代码。
定义一个自动注解
定义一个自定义注解,和spring boot提供的注解一般会有一个小的差别,就是自定义starter的pom.xml会引入自定义的configure项目,这样使用的时候,就可以少引入一个dependency了。或者干脆放到一个autoconfigure工程里面。
github上有一个比较完整、详细的实例,可以参见
备注参考:
spirng boot autoconfigure-徐敏博客:https://my.oschina.net/smartsales/blog/775550
自定义自动配置–github示例项目:https://github.com/snicoll-demos/spring-boot-master-auto-configuration
@Configuration如何使用–官方javadoc(比任何博文都全面完整):https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html
maven pom文件中的optional作用:http://blog.csdn.net/ado1986/article/details/39547839
@configuration无法注入的一个问题(建议不要像文章那样,而是最好使用@PropertySource):http://www.coderli.com/spring-configuration-autowire-failed/