();
+ for (Object object : values) {
+ wrappers.add((BeanLifecycleWrapper) object);
+ }
+ return wrappers;
+ }
+
+ public BeanLifecycleWrapper get(String name) {
+ return (BeanLifecycleWrapper) this.cache.get(name);
+ }
+
+ public BeanLifecycleWrapper put(String name, BeanLifecycleWrapper value) {
+ return (BeanLifecycleWrapper) this.cache.put(name, value);
+ }
+
+ }
+
+ /**
+ * Wrapper for a bean instance and any destruction callback (DisposableBean etc.) that
+ * is registered for it. Also decorates the bean to optionally guard it from
+ * concurrent access (for instance).
+ *
+ * @author Dave Syer
+ *
+ */
+ private static class BeanLifecycleWrapper {
+
+ private Object bean;
+
+ private Context> context;
+
+ private final String name;
+
+ @SuppressWarnings("rawtypes")
+ private final BeanLifecycleDecorator lifecycle;
+
+ private final ObjectFactory> objectFactory;
+
+ @SuppressWarnings("rawtypes")
+ public BeanLifecycleWrapper(String name, ObjectFactory> objectFactory,
+ BeanLifecycleDecorator lifecycle) {
+ this.name = name;
+ this.objectFactory = objectFactory;
+ this.lifecycle = lifecycle;
+ }
+
+ public void setDestroyCallback(Runnable callback) {
+ this.context = this.lifecycle.decorateDestructionCallback(callback);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getBean() {
+ if (this.bean == null) {
+ synchronized (this.name) {
+ if (this.bean == null) {
+ this.bean = this.lifecycle.decorateBean(
+ this.objectFactory.getObject(), this.context);
+ }
+ }
+ }
+ return this.bean;
+ }
+
+ public void destroy() {
+ if (this.context == null) {
+ return;
+ }
+ Runnable callback = this.context.getCallback();
+ if (callback != null) {
+ callback.run();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ BeanLifecycleWrapper other = (BeanLifecycleWrapper) obj;
+ if (this.name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ }
+ else if (!this.name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+}
diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java
index 8017a1d4..e27cb492 100644
--- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java
+++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/refresh/RefreshScope.java
@@ -1,153 +1,153 @@
-/*
- * Copyright 2002-2009 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.cloud.context.scope.refresh;
-
-import java.io.Serializable;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
-import org.springframework.cloud.context.scope.GenericScope;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.context.event.EventListener;
-import org.springframework.core.Ordered;
-import org.springframework.jmx.export.annotation.ManagedOperation;
-import org.springframework.jmx.export.annotation.ManagedResource;
-
-/**
- *
- * A Scope implementation that allows for beans to be refreshed dynamically at runtime
- * (see {@link #refresh(String)} and {@link #refreshAll()}). If a bean is refreshed then
- * the next time the bean is accessed (i.e. a method is executed) a new instance is
- * created. All lifecycle methods are applied to the bean instances, so any destruction
- * callbacks that were registered in the bean factory are called when it is refreshed, and
- * then the initialization callbacks are invoked as normal when the new instance is
- * created. A new bean instance is created from the original bean definition, so any
- * externalized content (property placeholders or expressions in string literals) is
- * re-evaluated when it is created.
- *
- *
- *
- * Note that all beans in this scope are only initialized when first accessed, so
- * the scope forces lazy initialization semantics. The implementation involves creating a
- * proxy for every bean in the scope, so there is a flag
- * {@link #setProxyTargetClass(boolean) proxyTargetClass} which controls the proxy
- * creation, defaulting to JDK dynamic proxies and therefore only exposing the interfaces
- * implemented by a bean. If callers need access to other methods then the flag needs to
- * be set (and CGLib present on the classpath). Because this scope automatically proxies
- * all its beans, there is no need to add <aop:auto-proxy/> to any bean
- * definitions.
- *
- *
- *
- * The scoped proxy approach adopted here has a side benefit that bean instances are
- * automatically {@link Serializable}, and can be sent across the wire as long as the
- * receiver has an identical application context on the other side. To ensure that the two
- * contexts agree that they are identical they have to have the same serialization id. One
- * will be generated automatically by default from the bean names, so two contexts with
- * the same bean names are by default able to exchange beans by name. If you need to
- * override the default id then provide an explicit {@link #setId(String) id} when the
- * Scope is declared.
- *
- *
- * @author Dave Syer
- *
- * @since 3.1
- *
- */
-@ManagedResource
-public class RefreshScope extends GenericScope
- implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor, Ordered {
-
- private ApplicationContext context;
- private BeanDefinitionRegistry registry;
- private boolean eager = true;
- private int order = Ordered.LOWEST_PRECEDENCE - 100;
-
- /**
- * Create a scope instance and give it the default name: "refresh".
- */
- public RefreshScope() {
- super.setName("refresh");
- }
-
- @Override
- public int getOrder() {
- return this.order;
- }
-
- public void setOrder(int order) {
- this.order = order;
- }
-
- /**
- * Flag to determine whether all beans in refresh scope should be instantiated eagerly
- * on startup. Default true.
- *
- * @param eager the flag to set
- */
- public void setEager(boolean eager) {
- this.eager = eager;
- }
-
- @Override
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
- throws BeansException {
- this.registry = registry;
- }
-
- @EventListener
- public void start(ContextRefreshedEvent event) {
- if (event.getApplicationContext() == this.context) {
- if (this.eager && this.registry != null) {
- for (String name : this.context.getBeanDefinitionNames()) {
- BeanDefinition definition = this.registry.getBeanDefinition(name);
- if (this.getName().equals(definition.getScope())
- && !definition.isLazyInit()) {
- this.context.getBean(name);
- }
- }
- }
- }
- }
-
- @ManagedOperation(description = "Dispose of the current instance of bean name provided and force a refresh on next method execution.")
- public boolean refresh(String name) {
- if (!name.startsWith(SCOPED_TARGET_PREFIX)) {
- // User wants to refresh the bean with this name but that isn't the one in the
- // cache...
- name = SCOPED_TARGET_PREFIX + name;
- }
- // Ensure lifecycle is finished if bean was disposable
- if (super.destroy(name)) {
- this.context.publishEvent(new RefreshScopeRefreshedEvent(name));
- return true;
- }
- return false;
- }
-
- @ManagedOperation(description = "Dispose of the current instance of all beans in this scope and force a refresh on next method execution.")
- public void refreshAll() {
- super.destroy();
- this.context.publishEvent(new RefreshScopeRefreshedEvent());
- }
-
- @Override
- public void setApplicationContext(ApplicationContext context) throws BeansException {
- this.context = context;
- }
-}
+/*
+ * Copyright 2002-2009 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.cloud.context.scope.refresh;
+
+import java.io.Serializable;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
+import org.springframework.cloud.context.scope.GenericScope;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.core.Ordered;
+import org.springframework.jmx.export.annotation.ManagedOperation;
+import org.springframework.jmx.export.annotation.ManagedResource;
+
+/**
+ *
+ * A Scope implementation that allows for beans to be refreshed dynamically at runtime
+ * (see {@link #refresh(String)} and {@link #refreshAll()}). If a bean is refreshed then
+ * the next time the bean is accessed (i.e. a method is executed) a new instance is
+ * created. All lifecycle methods are applied to the bean instances, so any destruction
+ * callbacks that were registered in the bean factory are called when it is refreshed, and
+ * then the initialization callbacks are invoked as normal when the new instance is
+ * created. A new bean instance is created from the original bean definition, so any
+ * externalized content (property placeholders or expressions in string literals) is
+ * re-evaluated when it is created.
+ *
+ *
+ *
+ * Note that all beans in this scope are only initialized when first accessed, so
+ * the scope forces lazy initialization semantics. The implementation involves creating a
+ * proxy for every bean in the scope, so there is a flag
+ * {@link #setProxyTargetClass(boolean) proxyTargetClass} which controls the proxy
+ * creation, defaulting to JDK dynamic proxies and therefore only exposing the interfaces
+ * implemented by a bean. If callers need access to other methods then the flag needs to
+ * be set (and CGLib present on the classpath). Because this scope automatically proxies
+ * all its beans, there is no need to add <aop:auto-proxy/> to any bean
+ * definitions.
+ *
+ *
+ *
+ * The scoped proxy approach adopted here has a side benefit that bean instances are
+ * automatically {@link Serializable}, and can be sent across the wire as long as the
+ * receiver has an identical application context on the other side. To ensure that the two
+ * contexts agree that they are identical they have to have the same serialization id. One
+ * will be generated automatically by default from the bean names, so two contexts with
+ * the same bean names are by default able to exchange beans by name. If you need to
+ * override the default id then provide an explicit {@link #setId(String) id} when the
+ * Scope is declared.
+ *
+ *
+ * @author Dave Syer
+ *
+ * @since 3.1
+ *
+ */
+@ManagedResource
+public class RefreshScope extends GenericScope
+ implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor, Ordered {
+
+ private ApplicationContext context;
+ private BeanDefinitionRegistry registry;
+ private boolean eager = true;
+ private int order = Ordered.LOWEST_PRECEDENCE - 100;
+
+ /**
+ * Create a scope instance and give it the default name: "refresh".
+ */
+ public RefreshScope() {
+ super.setName("refresh");
+ }
+
+ @Override
+ public int getOrder() {
+ return this.order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ /**
+ * Flag to determine whether all beans in refresh scope should be instantiated eagerly
+ * on startup. Default true.
+ *
+ * @param eager the flag to set
+ */
+ public void setEager(boolean eager) {
+ this.eager = eager;
+ }
+
+ @Override
+ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
+ throws BeansException {
+ this.registry = registry;
+ }
+
+ @EventListener
+ public void start(ContextRefreshedEvent event) {
+ if (event.getApplicationContext() == this.context) {
+ if (this.eager && this.registry != null) {
+ for (String name : this.context.getBeanDefinitionNames()) {
+ BeanDefinition definition = this.registry.getBeanDefinition(name);
+ if (this.getName().equals(definition.getScope())
+ && !definition.isLazyInit()) {
+ this.context.getBean(name);
+ }
+ }
+ }
+ }
+ }
+
+ @ManagedOperation(description = "Dispose of the current instance of bean name provided and force a refresh on next method execution.")
+ public boolean refresh(String name) {
+ if (!name.startsWith(SCOPED_TARGET_PREFIX)) {
+ // User wants to refresh the bean with this name but that isn't the one in the
+ // cache...
+ name = SCOPED_TARGET_PREFIX + name;
+ }
+ // Ensure lifecycle is finished if bean was disposable
+ if (super.destroy(name)) {
+ this.context.publishEvent(new RefreshScopeRefreshedEvent(name));
+ return true;
+ }
+ return false;
+ }
+
+ @ManagedOperation(description = "Dispose of the current instance of all beans in this scope and force a refresh on next method execution.")
+ public void refreshAll() {
+ super.destroy();
+ this.context.publishEvent(new RefreshScopeRefreshedEvent());
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext context) throws BeansException {
+ this.context = context;
+ }
+}
diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/thread/ThreadScope.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/thread/ThreadScope.java
index 8637cd2b..4b0070be 100644
--- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/thread/ThreadScope.java
+++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/scope/thread/ThreadScope.java
@@ -1,36 +1,36 @@
-/*
- * Copyright 2002-2009 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.cloud.context.scope.thread;
-
-import org.springframework.cloud.context.scope.GenericScope;
-
-/**
- *
- * @author Dave Syer
- *
- * @since 3.1
- *
- */
-public class ThreadScope extends GenericScope {
-
- /**
- * Create a scope instance and give it the default name: "thread".
- */
- public ThreadScope() {
- super();
- super.setName("thread");
- super.setScopeCache(new ThreadLocalScopeCache());
- }
-
-}
+/*
+ * Copyright 2002-2009 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.cloud.context.scope.thread;
+
+import org.springframework.cloud.context.scope.GenericScope;
+
+/**
+ *
+ * @author Dave Syer
+ *
+ * @since 3.1
+ *
+ */
+public class ThreadScope extends GenericScope {
+
+ /**
+ * Create a scope instance and give it the default name: "thread".
+ */
+ public ThreadScope() {
+ super();
+ super.setName("thread");
+ super.setScopeCache(new ThreadLocalScopeCache());
+ }
+
+}