Add RestartScope and Restart attributes
Add a "restart" Spring `Scope` that remains between application restarts. Allows beans such as the livereload server to remain active during restarts and not disconnect clients. See gh-3085
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.developertools.restart;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
/**
|
||||
* Restart {@code @Scope} Annotation used to indicate that a bean shoul remain beteen
|
||||
* restarts.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
* @see RestartScopeInitializer
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Scope("restart")
|
||||
public @interface RestartScope {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.developertools.restart;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.config.Scope;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
/**
|
||||
* Support for a 'restart' {@link Scope} that allows beans to remain between restarts.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public class RestartScopeInitializer implements
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
applicationContext.getBeanFactory().registerScope("restart", new RestartScope());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Scope} that stores beans as {@link Restarter} attributes.
|
||||
*/
|
||||
private static class RestartScope implements Scope {
|
||||
|
||||
@Override
|
||||
public Object get(String name, ObjectFactory<?> objectFactory) {
|
||||
return Restarter.getInstance().getOrAddAttribute(name, objectFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(String name) {
|
||||
return Restarter.getInstance().removeAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDestructionCallback(String name, Runnable callback) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveContextualObject(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConversationId() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -38,6 +39,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.CachedIntrospectionResults;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.developertools.restart.classloader.RestartClassLoader;
|
||||
import org.springframework.boot.logging.DeferredLog;
|
||||
@@ -89,6 +91,8 @@ public class Restarter {
|
||||
|
||||
private final UncaughtExceptionHandler exceptionHandler;
|
||||
|
||||
private final Map<String, Object> attributes = new HashMap<String, Object>();
|
||||
|
||||
private final BlockingDeque<LeakSafeThread> leakSafeThreads = new LinkedBlockingDeque<LeakSafeThread>();
|
||||
|
||||
private boolean finished = false;
|
||||
@@ -344,6 +348,22 @@ public class Restarter {
|
||||
}
|
||||
}
|
||||
|
||||
public Object getOrAddAttribute(final String name,
|
||||
final ObjectFactory<?> objectFactory) {
|
||||
synchronized (this.attributes) {
|
||||
if (!this.attributes.containsKey(name)) {
|
||||
this.attributes.put(name, objectFactory.getObject());
|
||||
}
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
public Object removeAttribute(String name) {
|
||||
synchronized (this.attributes) {
|
||||
return this.attributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the initial set of URLs as configured by the {@link RestartInitializer}.
|
||||
* @return the initial URLs or {@code null}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# Application Initializers
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.boot.developertools.restart.RestartScopeInitializer
|
||||
|
||||
# Application Listeners
|
||||
org.springframework.context.ApplicationListener=\
|
||||
org.springframework.boot.developertools.restart.RestartApplicationListener
|
||||
|
||||
Reference in New Issue
Block a user