Cache templates

This commit improves massively class loading performance by caching all
templates used by the generator. GroovyTemplate is now a bean rather than
a private utility.

Templates are cached by default and the cache is disabled automatically
if Devtools is in use (via a check of spring.groovy.template.cache).

Closes gh-288
This commit is contained in:
Stephane Nicoll
2016-09-13 14:34:10 +02:00
parent dd0442b5de
commit 61cc7eb41d
9 changed files with 100 additions and 40 deletions

View File

@@ -27,6 +27,7 @@ import io.spring.initializr.metadata.DependencyMetadataProvider
import io.spring.initializr.metadata.InitializrMetadataBuilder
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.metadata.InitializrProperties
import io.spring.initializr.util.GroovyTemplate
import io.spring.initializr.web.project.MainController
import io.spring.initializr.web.support.DefaultDependencyMetadataProvider
import io.spring.initializr.web.support.DefaultInitializrMetadataProvider
@@ -34,6 +35,7 @@ import io.spring.initializr.web.ui.UiController
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.bind.RelaxedPropertyResolver
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cache.Cache
import org.springframework.cache.CacheManager
@@ -43,6 +45,7 @@ import org.springframework.cache.concurrent.ConcurrentMapCache
import org.springframework.cache.support.SimpleCacheManager
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.env.Environment
import org.springframework.web.client.RestTemplate
/**
@@ -72,8 +75,11 @@ class InitializrAutoConfiguration {
@Bean
@ConditionalOnMissingBean
MainController initializrMainController() {
new MainController()
MainController initializrMainController(InitializrMetadataProvider metadataProvider,
GroovyTemplate groovyTemplate,
ProjectGenerator projectGenerator,
DependencyMetadataProvider dependencyMetadataProvider) {
new MainController(metadataProvider, groovyTemplate, projectGenerator, dependencyMetadataProvider)
}
@Bean
@@ -88,6 +94,16 @@ class InitializrAutoConfiguration {
new ProjectGenerator()
}
@Bean
@ConditionalOnMissingBean
GroovyTemplate groovyTemplate(Environment environment) {
def resolver = new RelaxedPropertyResolver(environment, 'spring.groovy.template.')
boolean cache = resolver.getProperty('cache', Boolean.class, true)
def groovyTemplate = new GroovyTemplate()
groovyTemplate.cache = cache
groovyTemplate
}
@Bean
@ConditionalOnMissingBean
ProjectRequestResolver projectRequestResolver() {

View File

@@ -21,14 +21,12 @@ import javax.servlet.http.HttpServletResponse
import io.spring.initializr.generator.InvalidProjectRequestException
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.util.GroovyTemplate
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.servlet.support.ServletUriComponentsBuilder
import static io.spring.initializr.util.GroovyTemplate.template
/**
* A base controller that uses a {@link InitializrMetadataProvider}
*
@@ -37,11 +35,16 @@ import static io.spring.initializr.util.GroovyTemplate.template
*/
abstract class AbstractInitializrController {
@Autowired
protected InitializrMetadataProvider metadataProvider
protected final InitializrMetadataProvider metadataProvider
private final GroovyTemplate groovyTemplate
private boolean forceSsl
protected AbstractInitializrController(InitializrMetadataProvider metadataProvider,
GroovyTemplate groovyTemplate) {
this.metadataProvider = metadataProvider
this.groovyTemplate = groovyTemplate
}
@PostConstruct
void initialize() {
forceSsl = metadataProvider.get().configuration.env.forceSsl
@@ -74,7 +77,7 @@ abstract class AbstractInitializrController {
// Google analytics support
model['trackingCode'] = metadata.configuration.env.googleAnalyticsTrackingCode
template templatePath, model
groovyTemplate.process templatePath, model
}
/**

View File

@@ -16,6 +16,9 @@
package io.spring.initializr.web.project
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.util.GroovyTemplate
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.ResponseBody
@@ -30,6 +33,10 @@ import org.springframework.web.bind.annotation.ResponseBody
@Deprecated
class LegacyStsController extends AbstractInitializrController {
LegacyStsController(InitializrMetadataProvider metadataProvider, GroovyTemplate groovyTemplate) {
super(metadataProvider, groovyTemplate)
}
@RequestMapping(value = '/sts', produces = 'text/html')
@ResponseBody
String stsHome() {

View File

@@ -24,7 +24,9 @@ import io.spring.initializr.generator.BasicProjectRequest
import io.spring.initializr.generator.CommandLineHelpGenerator
import io.spring.initializr.generator.ProjectGenerator
import io.spring.initializr.generator.ProjectRequest
import io.spring.initializr.metadata.InitializrMetadataProvider
import io.spring.initializr.util.Agent
import io.spring.initializr.util.GroovyTemplate
import io.spring.initializr.web.mapper.DependencyMetadataV21JsonMapper
import io.spring.initializr.web.mapper.InitializrMetadataJsonMapper
import io.spring.initializr.web.mapper.InitializrMetadataV21JsonMapper
@@ -67,14 +69,17 @@ class MainController extends AbstractInitializrController {
static final MediaType HAL_JSON_CONTENT_TYPE = MediaType.parseMediaType('application/hal+json')
@Autowired
private ProjectGenerator projectGenerator
@Autowired
private DependencyMetadataProvider dependencyMetadataProvider
private CommandLineHelpGenerator commandLineHelpGenerator = new CommandLineHelpGenerator()
private final ProjectGenerator projectGenerator
private final DependencyMetadataProvider dependencyMetadataProvider
private final CommandLineHelpGenerator commandLineHelpGenerator
MainController(InitializrMetadataProvider metadataProvider, GroovyTemplate groovyTemplate,
ProjectGenerator projectGenerator, DependencyMetadataProvider dependencyMetadataProvider) {
super(metadataProvider, groovyTemplate)
this.projectGenerator = projectGenerator
this.dependencyMetadataProvider = dependencyMetadataProvider
this.commandLineHelpGenerator = new CommandLineHelpGenerator(groovyTemplate)
}
@ModelAttribute
BasicProjectRequest projectRequest(@RequestHeader Map<String,String> headers) {