SpringBoot学习 @SpringBootApplication和热部署

接上篇文章,今天继续学习Spring Boot文档,

禁用具体的自动配置的类

在前面的文章中写道spring boot是可以在项目启动的时候,根据pom.xml中的spring boot依赖进行继承,相关的依赖会自动配置,那么如何来禁用其中某个自动配置的类,下面来说一下方法:

可以看一下@EnableAutoConfiguration注解的源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * 排除指定的自动配置类,这样它们就永远不会被执行
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * 如果要排除的类不在当前路劲中,可以使用该方法
	 * 排除,需要指定那些类的名字的全限定的类的名字,
	 * 这样它们就永远不会被执行
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

比如可以这样写:

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

最后,还可以使用spring.autoconfigure.exclude属性控制要排除的自动配置类的列表。

举例:@ComponentScan注解可以扫描到它的包及子包下的所有bean,比如下面这个例子:

package com.example.demo;

import com.example.demo.sub.ExtralClass;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        ExtralClass extra =  context.getBean(ExtralClass.class);
        System.out.println(extra);
    }
}
package com.example.demo.sub;

import org.springframework.stereotype.Component;

@Component
public class ExtralClass {
}

从代码可以看出来ExtraClassApplication.java的子包的类,我们通过在application.java中打印,发现执行了,而且打印出了如下的信息,说明该ExtralClass.java也被纳入到容器中进行管理。
在这里插入图片描述
当我们使用@SpringBootApplication注解中的属性对于指定的类进行排除,那么我们在启动项目的时候会看到一场信息,比如添加了exclude属性来禁用,让扫描不到ExtraClass

package com.example.demo;

import com.example.demo.sub.ExtralClass;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication(exclude = ExtralClass.class)
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        ExtralClass extra =  context.getBean(ExtralClass.class);
        System.out.println(extra);
    }
}

运行异常信息如下:
在这里插入图片描述
从异常信息中可以看出,这里说了,ExtralClass.java不是一个自动配置类,无法排除掉。
同样也可以使用@SpringBootApplication(excludeName = "com.example.demo.sub.ExtralClass"),效果和上图的错误信息提示一致。
Spring Bean和依赖注入

在我们的日常开发中,我们经常使用@ComponentScan注解来寻找你的Bean,通过使用@Autowired注解来进行构造器注入。

如果你在你的包的根目录中的application.class,你可以添加@ComponentScan注解(可以不写任何参数),你的应用的所有组件(@Component,@Service, @Repository,@Controller等等)会被自动的注册为Spring的容器。
下面的这个例子是使用了@Service注解,进行构造器注入来获取一个RiskAssessorBean。

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {
	private final RiskAssessor riskAssessor;
	@Autowired
	public DatabaseAccountService(RiskAssessor riskAssessor) {
		this.riskAssessor = riskAssessor;
	}
}

Bean的注入方式

关于Bean的注入我们有三种方式:
(1)构造器注入
(2)setter注入
(3)接口注入
其中我们最常用的第二种Setter注入的方式。

@SpringBootApplication注解

一般我们在spring boot项目中会使用@SpringBootApplication注解,因为它可以做到自动配置,组件类扫描和定义额外的配置类,也就是说一个注解可以达到三种效果,而这三种效果又相当于三个注解的作用,这三个等价注解分别是:
(1)@EnableAutoConfiguration:自动装配依赖
(2)@ComponentScan:在应用程序所在的包上启用@component 的扫描
(3)@Configuration:允许在上下文中注册额外的Bean,或者引入额外的配置类

因此@SpringBootApplication注解相当于@EnableAutoConfiguration@ComponentScan@Configuration注解的综合效果。

其实,在2.1.5版本中可以看@SpringBootApplication注解中没有明确写@Configuration注解,但是存在一个@SpringBootConfiguration注解,在该注解中包含一个@Configuration注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//该注解中存在@Configuration注解
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM,
				classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

@SpringBootApplication 也提供别名来定制这两个属性@EnableAutoConfiguration@ComponentScan.

比如,你不想使用@ComponentScan注解来扫描自动将bean纳入容器,你可以选择使用@Import注解自己手动写好需要纳入容器的类:

package com.example.myapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@EnableAutoConfiguration
@Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
	public static void main(String[] args) {
			SpringApplication.run(Application.class, args);
	}

}

如何来运行你的spring boot 的可执行jar

如果你将你的项目打包成为一个可执行的Jar,通过使用命令你可以运行你可执行的jar文件,你打包好的jar文件一般在你的target目录下面,如果要运行可以参考如下命令:

$ java -jar target/myapplication-0.0.1-SNAPSHOT.jar

还可以在启用远程调试支持的情况下运行打包应用程序。这样做可以将调试器附加到打包的应用程序,如下面的示例所示:

$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myapplication-0.0.1-SNAPSHOT.jar

使用Maven Plugin

Spring boot项目有maven plugin,其中包含了一个run的全局命令,它可以很快的编译并运行你的应用。下面是一个典型的例子:

$ mvn spring-boot:run

特别需要注意的是:当你的maven项目过大的时候,启动项目可能会抛出溢出的异常信息,此时,我们就需要设置一下maven的JVM参数,如下所示:

$ export MAVEN_OPTS=-Xmx1024m

使用Gradle插件
使用如下的命令:

$ gradle bootRun

如果项目启动的时候出现溢出,那么可以进行如下的操作系统设置:

$ export JAVA_OPTS=-Xmx1024m

总结:当出现溢出的时候,因为项目过大,此时我们就需要调整JVM参数,来调整一下堆的大小


热部署

可以采用JRebel插件spring boot也提供了spring-boot-devtools模块支持快速重启应用程序。

pom.xml文件中,你可以添加如下的依赖:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
	<optional>true</optional>
</dependency>

如果是在gradle中,可以添加如下的依赖:

configurations {
	developmentOnly
	runtimeClasspath {
		extendsFrom developmentOnly
	}
}
dependencies {
	developmentOnly("org.springframework.boot:spring-boot-devtools")
}

当你运行一个完整的包应用的时候,开发工具是被自动禁止的。如果你的应用是通过java -jar命令来运行或者是从一个特殊的加载器启动,那么该应用就会被认为是一个“生产应用”。如果不适用于你,那么你就应该考虑排除掉devtools或者在系统属性中进行如下的设置-Dspring.devtools.restart.enable=false
默认情况下,重新打包的存档不包含devtools。如果要使用某个远程devtools功能,则需要禁用excludedevtools build属性来包含它。MavenGradle插件都支持该属性。


默认的属性

SpringBoot支持的几个库使用缓存来提高性能。例如,模板引擎缓存已编译的模板,以避免重复解析模板文件。此外,SpringMVC还可以在服务静态资源时向响应添加HTTP缓存头。
虽然缓存在生产中非常有益,但在开发过程中它可能会适得其反,从而阻止您看到刚刚在应用程序中所做的更改。因此,Spring-boot-devtools默认禁用缓存。
缓存选项通常在application.properties文件中进行设置。例如,thymeleaf提供spring.thymeleaf.cache属性。Springbootdevtools模块不需要手动设置这些属性,而是自动应用合理的开发时间配置。
因为在开发SpringMVCSpringWebFlux应用程序时需要更多关于Web请求的信息,开发人员工具将为Web日志记录组启用DEBUG日志记录。这将为您提供有关传入请求、哪个处理程序正在处理它、响应结果等的信息。如果您希望记录所有请求详细信息(包括潜在的敏感信息),可以打开spring.http.log-request-details配置属性。

如果你不希望使用默认的属性,那么你可以在application.properties中设置spring.devtools.add-properties=false

可以去这个类DevToolsPropertyDefaultsPostProcessor中查看完整的devtools中包含的属性:

static {
		Map<String, Object> properties = new HashMap<>();
		properties.put("spring.thymeleaf.cache", "false");
		properties.put("spring.freemarker.cache", "false");
		properties.put("spring.groovy.template.cache", "false");
		properties.put("spring.mustache.cache", "false");
		properties.put("server.servlet.session.persistent", "true");
		properties.put("spring.h2.console.enabled", "true");
		properties.put("spring.resources.cache.period", "0");
		properties.put("spring.resources.chain.cache", "false");
		properties.put("spring.template.provider.cache", "false");
		properties.put("spring.mvc.log-resolved-exception", "true");
		properties.put("server.error.include-stacktrace", "ALWAYS");
		properties.put("server.servlet.jsp.init-parameters.development", "true");
		properties.put("spring.reactor.stacktrace-mode.enabled", "true");
		PROPERTIES = Collections.unmodifiableMap(properties);
	}

自动重启

当你的应用中不管什么时间,有文件变动的时候,应用使用spring-boot-devtools自动重启。在你使用IDE的时候这个最有助于开发,避免你手动启动项目,目前在我们项目中,我的IDEA中旧装了JRebel插件,当你的文件有改动的时候,项目就会自动编译改动过的文件。对于静态的资源是不需要重新启动应用的。
触发重新启动
由于devtools监视类路径资源,触发重新启动的唯一方法是更新类路径。导致类路径更新的方式取决于您使用的IDE。在Eclipse中,保存修改过的文件会导致类路径更新并触发重新启动。在intellij思想中,构建项目(build->build project)具有相同的效果。

DevTools是依赖于应用上下文关闭hook的,如果你进行了如下的设置
SpringApplication springApplication = new SpringApplication(); springApplication.setRegisterShutdownHook(false);
那么它当前就不可以正常工作。
当确定类路径上的条目在更改时是否应触发重新启动时,devtools会自动忽略名为:spring-boot, spring-boot-devtools, spring-boot-autoconfigure, spring-boot-actuator, 和spring-boot-starter.
devtools需要自定义applicationContext使用的resourceloader。如果您的应用程序已经提供了一个,那么它将被包装。不支持直接重写ApplicationContext上的getResource方法。

重新启动与重新加载

SpringBoot提供的重启技术通过使用两个类加载器来工作。不更改的类(例如,来自第三方JAR的类)被加载到基本类加载器中。您正在积极开发的类将加载到重新启动的类加载器中。重新启动应用程序时,会丢弃重新启动类加载器并创建新的类加载器。这种方法意味着应用程序的重新启动通常比“冷启动”快得多,因为基本类加载器已经可用并已填充。
如果您发现重启对于您的应用程序来说不够快,或者遇到了类加载问题,那么您可以考虑重新加载技术,如jrebel from zeroturnary。这些方法是在加载类时重写类,以使它们更易于重新加载。

总结:所以说,我们使用JRebel是对你修改过的类文件进行重新加载,然后利用,而不是重新启动项目,来加载所有的类文件。


记录条件评估中的更改
默认情况下,每次重新启动应用程序时,都会记录一个显示条件评估增量的报告。当您进行诸如添加或删除bean以及设置配置属性等更改时,报告将显示对应用程序自动配置的更改。
要禁用报告的日志记录,请设置以下属性:

spring.devtools.restart.log-condition-evaluation-delta=false

资源排除

当某些资源发生变动的时候是不需要重新启动的。比如Thymeleaf模板可以被及时的编辑。默认的,改变这些下面的资源的时候,不会触发项目重新启动,但是会触发一个live reload/META-INF/maven, /META-INF/resources, /resources, /static, /public, 或者 /templates。如果你想定制这些排除,你可以使用spring.devtools.restart.exclude属性,例如,排除掉/static/public下改动的资源:

spring.devtools.restart.exclude=statis/**,public/**

如果要保留这些默认值并添加其他排除项,请改用spring.devtools.restart.additional-exclude属性。

类路径之外的文件变动
你或许想要你的应用重新启动或者加载当你改变了一些不在当前类路径的文件。此时可以使用spring.devtools.restart.additional-paths属性来配置额外的路径来关注文件的变化。您可以使用前面描述的spring.devtools.restart.exclude属性控制附加路径下的更改是触发完全重新启动还是实时重新加载。
禁用重启项
在你不想使用重启项的时候,你可以使用spring.devtools.restart.enabled属性的设置来禁用重新启动。在大多数情况下,你可以在application.properties文件中进行设置:

spring.devtools.restart.enabled=false

(虽然你禁用了重新启动的属性,仍然会初始化重启加载器,但是它会忽略文件的变动)
如果你想完全禁用重启项支持(例如,因为它不适用于特定的类库),在调用SpringApplication.run(...)方法之前,你可以设置spring.devtools.restart.enabled属性通过System.,例如:

public static void main(String[] args) {
	System.setProperty("spring.devtools.restart.enabled", "false");
	SpringApplication.run(MyApp.class, args);
}

使用触发器文件
如果您使用的是一个持续编译更改文件的IDE,那么您可能更喜欢只在特定的时间触发重启。为此,您可以使用“触发器文件”,这是一个特殊的文件,当您想要实际触发重新启动检查时,必须对其进行修改。更改文件只会触发检查,仅当devtools检测到必须执行某些操作时才会重新启动。触发器文件可以手动更新,也可以使用IDE插件更新。
要使用触发器文件,请将spring.devtools.restart.trigger-file属性设置为触发器文件的路径
您可能希望将spring.devtools.restart.trigger-file设置为全局设置,以便所有项目的行为方式都相同。
自定义重新启动类加载器
上面讨论过重新启动和重新加载的区别,重新启动是需要两个类加载器,一个是未改变的类的加载器,一个是有改动的类的加载器。对于大多数应用,重新启动都是管用的。但是,有时候重新启动会造成一些加载的问题。
默认的,任何开源的项目在IDE中被加载都是通过“重新启动restart"加载器,任何正规的.jar文件被加载都是通过"基本"的类加载器。如果你的项目处于一个多模块化,并且不是所有的模块都引入到你的IDE中,那么你或许需要定制化一些东西,这样你就需要创建一个META-INF/spring-devtools.properties文件。
这个文件是干嘛用的?它里面包含了一些包含前缀为restart.excluderestart.include的属性。include元素是应该是被放入“restart”类加载器的类别,exclude元素是应该放入“base”类加载器的项。属性的值是应用于类路径的正则表达式模式,如下例所示:

restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar

所有的属性的key都应该是独一无二的,而且所有的key都应该用restart.include.或者restart.exclude.开头。
将加载类路径中的所有meta-inf/spring-devtools.properties。您可以将文件打包到项目内部或项目使用的库中。
已知限制
重新启动功能不适用于使用标准ObjectInputstream反序列化的对象。如果需要反序列化数据,可能需要将SpringconfigurableObjectInputstreamthread.currentThread().getContextClassLoader()结合使用。
不幸的是,一些第三方库在不考虑上下文类加载器的情况下反序列化。如果你发现这样一个问题,你需要向原始作者请求修复。
LiveReoload
spring-boot-devtools模块包含一个内嵌的LiveReload服务,当资源文件有改动的时候可以被用来触发浏览器刷新。LiveReload浏览器的扩展对于Chrome, Firefox 和Safari来说是可以利用的。
你只可以一次运行一个LiveReload服务。在你启动你的应用之前,确保没有其他的LiveReload服务正在运行。如果你从你的IDE中启动多个应用,那么只有第一个LiveReload是被支持的。
全局设置
可以通过将名为.spring-boot-devtools.properties的文件添加到$home文件夹来配置全局devtools设置(请注意,文件名以“.”开头)。添加到此文件的任何属性都将应用于使用devtools的计算机上的所有Spring引导应用程序。例如,要将Restart配置为始终使用触发器文件,您需要添加以下属性:
~/.spring-boot-devtools.properties.
spring.devtools.reload.trigger-file=.reloadtrigger
[注意]
.spring-boot-devtools.properties中激活的配置文件不会影响特定配置文件的加载。
远程应用
spring boot开发者工具不仅限于本地的开发,而且当你远程运行应用的时候还可以使用一些新特性。远程支持即opt-in。你应该确保你的devtools被包含在重新打包的存档中。

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<excludeDevtools>false</excludeDevtools>
			</configuration>
		</plugin>
	</plugins>
</build>

你应该设置spring.devtools.remote.secret=mysecret,在远程应用上面启动spring-boot-devtools是存在安全风险的。建议不要在远程应用中开启这个支持。
远程devtools支持分为两部分:接受连接的服务器端端点和在IDE中运行的客户端应用程序。设置spring.devtools.remote.secret属性时,将自动启用服务器组件。必须手动启动客户端组件。


运行远程客户端应用程序
远程客户端应用程序设计为从您的IDE中运行。您需要使用与所连接的远程项目相同的类路径运行。org.springframework.boot.devtools.RemoteSpringApplication。应用程序的单个必需参数是它所连接的远程URL。
例如,如果你正在使用Eclipse或者STS,并且你的项目名字叫做my-app,你要把该项目部署到云端,那么你将做下面的事情:
(1)选择Run Configurations...Run菜单中
(2)创建一个新的Java应用程序来运行配置
(3)使用org.springframework.boot.devtools.RemoteSpringApplication作为main
(4)将https://myapp.cfapps.io添加到Program arguments(或任何远程URL)。
一个运行的远程客户端或许像下面显示的这样:

 .   ____          _                                              __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _          ___               _      \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |        | _ \___ _ __  ___| |_ ___ \ \ \ \
 \\/  ___)| |_)| | | | | || (_| []::::::[]   / -_) '  \/ _ \  _/ -_) ) ) ) )
  '  |____| .__|_| |_|_| |_\__, |        |_|_\___|_|_|_\___/\__\___|/ / / /
 =========|_|==============|___/===================================/_/_/_/
 :: Spring Boot Remote :: 2.1.5.RELEASE

2015-06-10 18:25:06.632  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Starting RemoteSpringApplication on pwmbp with PID 14938 (/Users/pwebb/projects/spring-boot/code/spring-boot-devtools/target/classes started by pwebb in /Users/pwebb/projects/spring-boot/code/spring-boot-samples/spring-boot-sample-devtools)
2015-06-10 18:25:06.671  INFO 14938 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2a17b7b6: startup date [Wed Jun 10 18:25:06 PDT 2015]; root of context hierarchy
2015-06-10 18:25:07.043  WARN 14938 --- [           main] o.s.b.d.r.c.RemoteClientConfiguration    : The connection to http://localhost:8080 is insecure. You should use a URL starting with 'https://'.
2015-06-10 18:25:07.074  INFO 14938 --- [           main] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2015-06-10 18:25:07.130  INFO 14938 --- [           main] o.s.b.devtools.RemoteSpringApplication   : Started RemoteSpringApplication in 0.74 seconds (JVM running for 1.105)

因为远程客户端应用使用的是与实际应用程序相同的类路径,所以它可以直接读取应用程序属性。这是如何读取spring.devtools.remote.secret属性并将其传递给服务器进行身份验证。
建议将https://作为连接协议,以便在传递的过程中加密,密码不会被拦截。
如果你想使用一个代理来访问远程应用,配置一下下面两个属性:

spring.devtools.remote.proxy.host
spring.devtools.remote.proxy.port

远程更新

远程客户端以与本地重新启动相同的方式监视应用程序类路径的更改。任何更新的资源都被推送到远程应用程序,并且(如果需要)触发重新启动。如果您迭代一个使用本地没有的云服务的功能,这将很有帮助。通常,远程更新和重新启动要比完全重建和部署周期快得多。
只有在远程客户端运行时才监视文件。如果在启动远程客户端之前更改了文件,则不会将其推送到远程服务器。

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值