注解RefreshScope是对注解@Scope
的增强,并且是被spring-cloud-context
依赖引进的,但是注解@Scope是Spring自身携带的增强点。
@Scope提供的Mode类型存在default、no、interface、target_class 4种类型,@RefreshScope是在Scope基础上增加了refresh
类型。
1.Scope
public class ClassPathBeanDefinitionScanner{
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {//应用启动类所在的包路径
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);// 获取到全部的候选类
for (BeanDefinition candidate : candidates) {
// 解析当前类存在Scope注解
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
//设置Scope的范围:单例singleton、原型prototype、refresh。对于@RefreshScope分析其Scope 为 refresh
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//此处针对RefreshScope注解的bean,生成两个BeanDefinition注册在DefaultListableBeanFactory#beanDefinitionMap属性中。
//其中之一:bean为 scopedTarget.xxx,BeanDefinition中beanClass属性为目标类信息。
//其中之一:bean位xxx ,其中BeanDefinition中beanClass属性为通过ScopedProxyMode设置为ScopedProxyFactoryBean。
// ScopedProxyFactoryBean 为FactoryBean
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
}
以上即为SpringBoot启动流程中遍历启动类所在包下全部的候选类,针对@Scope注解判断这些潜在候选类是否需要ScopedProxyFactoryBean
代理处理。
2.RefreshAutoConfiguration
核心类RefreshAutoConfiguration
是为了注解RefreshScope
引入的,同时引入两个BeanDefinitionRegistryPostProcessor
类型的后置处理器之RefreshScopeBeanDefinitionEnhancer
& RefreshScope
,即只要存在包spring-cloud-context,该后置处理器就会发挥作用。
public class RefreshAutoConfiguration {
@Bean
@ConditionalOnMissingBean(RefreshScope.class)
public static RefreshScope refreshScope() {
return new RefreshScope();
}
@Bean
@ConditionalOnMissingBean
public ContextRefresher contextRefresher(ConfigurableApplicationContext context,RefreshScope scope) {
return new ContextRefresher(context, scope);
}
@Bean
public RefreshEventListener refreshEventListener(ContextRefresher contextRefresher) {
return new RefreshEventListener(contextRefresher);
}
@Component
protected static class RefreshScopeBeanDefinitionEnhancer implements BeanDefinitionRegistryPostProcessor{
private Set<String> refreshables = new HashSet<>(Arrays.asList("com.zaxxer.hikari.HikariDataSource"));
public static final String REFRESH_SCOPE_NAME = "refresh";
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry){
bindEnvironmentIfNeeded(registry);
//从IOC注册表中遍历所有候选bean
for (String name : registry.getBeanDefinitionNames()) {
BeanDefinition definition = registry.getBeanDefinition(name);
if (isApplicable(registry, name, definition)) {
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition,name);
// 将当前bean BeanDefinition中class属性重置为 ScopedProxyFactoryBean
BeanDefinitionHolder proxy = ScopedProxyUtils.createScopedProxy(holder, registry, true);
definition.setScope("refresh");
if (registry.containsBeanDefinition(proxy.getBeanName())) {
registry.removeBeanDefinition(proxy.getBeanName());
}
registry.registerBeanDefinition(proxy.getBeanName(),proxy.getBeanDefinition());
}
}
}
private boolean isApplicable(BeanDefinitionRegistry registry, String name,BeanDefinition definition) {
String scope = definition.getScope();
if (REFRESH_SCOPE_NAME.equals(scope)) {// 如果当前bean之scope属性即为refresh则无需代理
return false;
}
String type = definition.getBeanClassName();
if (!StringUtils.hasText(type) && registry instanceof BeanFactory) {
Class<?> cls = ((BeanFactory) registry).getType(name);
if (cls != null) {
type = cls.getName();
}
}
// 如果当前类的类型为com.zaxxer.hikari.HikariDataSource,则对其进行代理
if (type != null) {
return this.refreshables.contains(type);
}
return false;
}
}
}
但是需要注意的是:RefreshScopeBeanDefinitionEnhancer是专门针对dataSource为com.zaxxer.hikari.HikariDataSource类型的bean。
2.1.RefreshScope
public class RefreshScope{
// BeanDefinitionRegistryPostProcessor类型的后置处理器 核心回调方法
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry){
this.registry = registry;
super.postProcessBeanDefinitionRegistry(registry);//GenericScope#postProcessBeanDefinitionRegistry
}
}
public class GenericScope{
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry){
// 遍历全部的BeanDefinition,BeanDefinition是后续实例化bean需要的类信息
for (String name : registry.getBeanDefinitionNames()) {
BeanDefinition definition = registry.getBeanDefinition(name);
if (definition instanceof RootBeanDefinition) {
RootBeanDefinition root = (RootBeanDefinition) definition;
if (root.getDecoratedDefinition() != null && root.hasBeanClass()
&& root.getBeanClass() == ScopedProxyFactoryBean.class) {// 处理ScopedProxyFactoryBean类型的bean
if (getName().equals(root.getDecoratedDefinition().getBeanDefinition().getScope())) {
// 将 ScopedProxyFactoryBean类型的bean 再次设置为 LockedScopedProxyFactoryBean类型的bean
root.setBeanClass(LockedScopedProxyFactoryBean.class);
root.getConstructorArgumentValues().addGenericArgumentValue(this);
root.setSynthetic(true);
}
}
}
}
}
}
相较于Scope,RefreshScope引入LockedScopedProxyFactoryBean
类型。
3.LockedScopedProxyFactoryBean
通过上面章节得知,存在@RefreshScope的bean其BeanDefinition中Class属性为FactoryBean类型的class,即LockedScopedProxyFactoryBean。
- LockedScopedProxyFactoryBean实现了BeanFactoryAware接口。
- 实现MethodInterceptor接口实现对目标bean做Cglib代理处理。
public static class LockedScopedProxyFactoryBean<S extends GenericScope>
extends ScopedProxyFactoryBean implements MethodInterceptor {
private final S scope;
private String targetBeanName;//scopedTarget.xxx
public LockedScopedProxyFactoryBean(S scope) {
this.scope = scope;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
// ScopedProxyFactoryBean#setBeanFactory 对目标bean做Cglib代理
super.setBeanFactory(beanFactory);
Object proxy = getObject();
if (proxy instanceof Advised) {
Advised advised = (Advised) proxy;
advised.addAdvice(0, this);
}
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
if (AopUtils.isEqualsMethod(method) || AopUtils.isToStringMethod(method)
|| AopUtils.isHashCodeMethod(method)
|| isScopedObjectGetTargetObject(method)) {
return invocation.proceed();
}
Object proxy = getObject();
ReadWriteLock readWriteLock = this.scope.getLock(this.targetBeanName);
if (readWriteLock == null) {
readWriteLock = new ReentrantReadWriteLock();
}
Lock lock = readWriteLock.readLock();
lock.lock();
if (proxy instanceof Advised) {
Advised advised = (Advised) proxy;
ReflectionUtils.makeAccessible(method);
return ReflectionUtils.invokeMethod(method,
advised.getTargetSource().getTarget(),
invocation.getArguments());
}
return invocation.proceed();
}
}
3.1.ScopedProxyFactoryBean
public class ScopedProxyFactoryBean extends ProxyConfig
implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {
private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();
@Nullable
private String targetBeanName;
@Nullable
private Object proxy;
public ScopedProxyFactoryBean() {
setProxyTargetClass(true);
}
public void setTargetBeanName(String targetBeanName) {
this.targetBeanName = targetBeanName;
this.scopedTargetSource.setTargetBeanName(targetBeanName);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
this.scopedTargetSource.setBeanFactory(beanFactory);
ProxyFactory pf = new ProxyFactory();
pf.copyFrom(this);
// 目标类创建代理,注意是对scopedTargetSource对应的class
pf.setTargetSource(this.scopedTargetSource);
// 获取目标类的Class对象
Class<?> beanType = beanFactory.getType(this.targetBeanName);
if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
}
ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));
pf.addInterface(AopInfrastructureBean.class);
this.proxy = pf.getProxy(cbf.getBeanClassLoader());
}
@Override
public Object getObject() {
if (this.proxy == null) {
throw new FactoryBeanNotInitializedException();
}
return this.proxy;
}
}
如上所示,对目标类实例化过程中由于其BeanDefinition的class为FactoryBean类型的属性值,即存在代理过程。但是代理对象并非存在于IOC容器中,而是通过FactoryBean#getObject实时获取。
4.真正的代理过程
解析HTTP请求过程中,存在通过beanName获取handler过程,如下:
public abstract class AbstractBeanFactory{
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
//此时根据beanName从IOC容器中获取的是LockedScopedProxyFactoryBean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {// 如果获取scopedTarget.xxx对应的bean实例信息
BeanFactory parentBeanFactory = getParentBeanFactory();
...
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
...
if (mbd.isSingleton()) {//scope表示为单例
...
}else if (mbd.isPrototype()) {//scope表示为Prototype
...
}else {//scope表示为refresh
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);//获取到RefreshScope
final Scope scope = this.scopes.get(scopeName);
// 从RefreshScope中获取scopedTarget.xxx对应的bean实例信息,存在则返回,否则通过Lambda表达式新建实例信息
// scope#get涉及目标类的缓存信息,如果存在缓存表明目标类对应的配置信息没有发生变化。
// 没有缓存则新建目标类的实例信息,实例化过程也就是对其属性重新赋值的过程,即最新的value值,实现了配置信息动态刷新的功能
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}
});
//scopedInstance 即目标类的实例信息,此时scopedTarget.xxx获取到的就是普通的bean
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
}
...
return (T) bean;
}
protected Object getObjectForBeanInstance(Object beanInstance,String name,String beanName,RootBeanDefinition mbd) {
//如果beanInstance 不是 FactoryBean 则直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 此处就是通过 FactoryBean#getObject获取到目标类的代理对象
Object object = getObjectFromFactoryBean(factory, beanName, !synthetic);
...
return object;
}
}
通过上述得知目标类最终得到其Cglib代理的对象,执行目标方法时被如下方法拦截:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
//advised.getTargetSource:从ProxyFactory中获取targetSource,即scopedTarget.xxx对应的类信息
TargetSource targetSource = this.advised.getTargetSource();
...
// 获取TargetSource实例中目标source即scopedTarget.xxx对应的bean实例信息。继续调用上述AbstractBeanFactory#doGetBean方法
// 涉及本文中核心逻辑之配置信息动态刷新
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain,
methodProxy).proceed();// 最终执行目标类的目标方法
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
}
综上所述得知配置信息动态刷新的过程。还缺少一环即配置更新同时删除目标类实例在GenericScope中缓存值。