目录
RefreshScope 代理过程
RefreshScope 刷新过程
在SpringCloud 中将组建添加 @RefreshScope 可以实现动态刷新,要实现自动更新,那么需要
SpringCloud 使用@RefreshScope 来解决动态刷新,查看注解, 以 @RefreshScope 声明的Bean将会被 org.springframework.cloud.context.scope.refresh.RefreshScope 代理
/**
* Convenience annotation to put a @Bean
definition in
* {@link org.springframework.cloud.context.scope.refresh.RefreshScope refresh scope}.
* Beans annotated this way can be refreshed at runtime and any components that are using
* them will get a new instance on the next method call, fully initialized and injected
* with all dependencies.
* 这里意思是:以RefreshScope这种方式声明的bean将会在运行时被刷新,所有使用它的组件下一次方法调用的时候会得到一个初始化完整的bean,包含其依赖关系
* @author Dave Syer
*
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {
/**
* @see Scope#proxyMode()
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {
@AliasFor("scopeName")
String value() default "";
/**
* singleton 表示该bean是单例的(默认)
* prototype 表示该bean是多例的,即每次使用该bean时都会新建一个对象
* request 在一次http请求中一个bean对应一个实例
* session 在一个httpSession中一个bean对应一个实例
*/
@AliasFor("value")
String scopeName() default "";
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}
@RefreshScope 是一个复合注解 ,并标识ScopedProxyMode = ScopedProxyMode.TARGET_CLASS
1. ScopedProxyMode 枚举有4个属性
ScopedProxyMode .DEFAULT 默认值和ScopedProxyMode .NO 相同
ScopedProxyMode .NO 表示不需要代理,直接创建
ScopedProxyMode.INTERFACES 表示通过JDK动态代理创建类
ScopedProxyMode.TARGET_CLASS 表示通过CGLIB动态代理方式创建类
2. @Scope 代表了Bean的作用域,sigleton 单例,prototype 多例,request 一次http请求对应一个实例, session 一个httpsession中一个bean对应一个实例
3. @Scope("refresh") 表示 @RefreshScope 是scopeName="refresh"的 @Scope
//代码片段1
@ManagedResource
public class RefreshScope extends GenericScope
implements ApplicationContextAware, Ordered {
private ApplicationContext context;
private BeanDefinitionRegistry registry;
private boolean eager = true;
private int order = Ordered.LOWEST_PRECEDENCE - 100;
// 初始化的时候设置了name属性为refresh
public RefreshScope() {
super.setName("refresh");
}
......
}
//代码片段2
public class GenericScope implements Scope, BeanFactoryPostProcessor,
BeanDefinitionRegistryPostProcessor, DisposableBean {
private String name = "generic";
//默认名称是generic ,RefreshScope 将其修改成了"refresh"
public void setName(String name) {
this.name = name;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
this.beanFactory = beanFactory;
//这里向BeanFactory注册Scope ,注册了refresh 名称和RefreshScope
beanFactory.registerScope(this.name, this);
setSerializationId(beanFactory);
}
}
//
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
//内置1个Map存储注册的Scope
private final Map scopes = new LinkedHashMap<>(8);
@Override
public void registerScope(String scopeName, Scope scope) {
Assert.notNull(scopeName, "Scope identifier must not be null");
Assert.notNull(scope, "Scope must not be null");
if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
}
//注册后,保存到scopes中,这是1个map key=refresh ,values=RfreshScope
Scope previous = this.scopes.put(scopeName, scope);
if (previous != null && previous != scope) {
if (logger.isInfoEnabled()) {
logger.info("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
}
}
}
}
// 代码片段3
// AbstractBeanFactory# doGetBean 方法: 创建Bean实例的处理方式
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//...
//L313开始
//如果是单例:Bean配置成“singleton” 或者未配置的时候
if (mbd.isSingleton()) {
}
//Bean配置成“prototype” 的时候
else if (mbd.isPrototype()) {
}
//配置成refesh分支的时候
else {
//Scope Bean实例交由Scope自己创建
String scopeName = mbd.getScope();
//这里通过"refresh" 得到注册的RefreshScope
//通过RefreshScope 来创建Bean,前面说了RefreshScope 通过GCLIB动态代理创建BEAN
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
public class RefreshEventListener {
private ContextRefresher refresh;
@EventListener
public void handle(RefreshEvent event) {
if (this.ready.get()) { // don't handle events before app is ready
log.debug("Event received " + event.getEventDesc());
//刷新
Set keys = this.refresh.refresh();
log.info("Refresh keys changed: " + keys);
}
}
}
//-----------------ContextRefresher ---------------------
public class ContextRefresher {
private ConfigurableApplicationContext context;
private RefreshScope scope;
//.....
public synchronized Set refresh() {
//刷新环境
Set keys = refreshEnvironment();
//刷新 RefreshScope
this.scope.refreshAll();
return keys;
}
public synchronized Set refreshEnvironment() {
Map before = extract(
this.context.getEnvironment().getPropertySources());
addConfigFilesToEnvironment();
Set keys = changes(before,
extract(this.context.getEnvironment().getPropertySources())).keySet();
this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
return keys;
}
//.....
}
//------------------RefreshScope --------------------
@ManagedResource
public class RefreshScope extends GenericScope
implements ApplicationContextAware, Ordered {
// 销毁RefreshScope 中的bean, 强制下一次执行的时候刷新
@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());
}
}
//-----------------GenericScope ---------------------
public class GenericScope implements Scope, BeanFactoryPostProcessor,
BeanDefinitionRegistryPostProcessor, DisposableBean {
private BeanLifecycleWrapperCache cache = new BeanLifecycleWrapperCache(
new StandardScopeCache());
//..
//销毁
@Override
public void destroy() {
List errors = new ArrayList();
// 清空缓存
Collection wrappers = this.cache.clear();
for (BeanLifecycleWrapper wrapper : wrappers) {
try {
Lock lock = locks.get(wrapper.getName()).writeLock();
lock.lock();
try {
wrapper.destroy(); //销毁
}
finally {
lock.unlock();
}
}
catch (RuntimeException e) {
errors.add(e);
}
}
if (!errors.isEmpty()) {
throw wrapIfNecessary(errors.get(0));
}
this.errors.clear();
}
//再次获取的时候重新通过工厂获取新值
@Override
public Object get(String name, ObjectFactory> objectFactory) {
BeanLifecycleWrapper value = this.cache.put(name,
new BeanLifecycleWrapper(name, objectFactory));
locks.putIfAbsent(name, new ReentrantReadWriteLock());
try {
return value.getBean();
}
catch (RuntimeException e) {
this.errors.put(name, e);
throw e;
}
}
public Object getBean() {
if (this.bean == null) {
synchronized (this.name) {
if (this.bean == null) {
//bean不存在的时候创建
this.bean = this.objectFactory.getObject();
}
}
}
return this.bean;
}
}
下一篇:Nacos 配置中心原理(Nacos +SpringCloud)