All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.cloud.context.scope.refresh.RefreshScope Maven / Gradle / Ivy

/*
 * Copyright 2012-2019 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
 *
 *      https://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.cloud.context.scope.GenericScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
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 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, ApplicationListener, Ordered { private ApplicationContext context; private BeanDefinitionRegistry registry; private boolean eager = true; private int order = Ordered.LOWEST_PRECEDENCE - 100; /** * Creates a scope instance and gives 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; super.postProcessBeanDefinitionRegistry(registry); } @Override public void onApplicationEvent(ContextRefreshedEvent event) { start(event); } public void start(ContextRefreshedEvent event) { if (event.getApplicationContext() == this.context && this.eager && this.registry != null) { eagerlyInitialize(); } } private void eagerlyInitialize() { for (String name : this.context.getBeanDefinitionNames()) { BeanDefinition definition = this.registry.getBeanDefinition(name); if (this.getName().equals(definition.getScope()) && !definition.isLazyInit()) { Object bean = this.context.getBean(name); if (bean != null) { bean.getClass(); } } } } @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; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy