注解RefreshScope时一个组合注解。
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {
// Scope代理模式之ScopedProxyMode,包含TARGET_CLASS、INTERFACES、DEFAULT、NO
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
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;
}
}
后续解析目标bean时其类信息为ScopedProxyFactoryBean。但其实在解析RefreshScope中最终将其设置为LockedScopedProxyFactoryBean,具体参考以下章节。
当前类是通过自动装配候选类RefreshAutoConfiguration
触发的。
通过上述UML图得知其几点重要信息:
public class RefreshScope{
// BeanDefinitionRegistryPostProcessor类型的后置处理器 核心回调方法
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
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);
}
}
}
}
}
}
通过上述得知,在DefaultListableBeanFactory#beanDefinitionMap中存在两种类型目标类相关的BeanDefinition。那是不是意味着在IOC容器中也存在目标类相关的两种的bean呢?
事实是scopedTarget.xxx类型的BeanDefinition其scope为refresh并非单例所以不会实例化。xxx类型在IOC容器中的单例为LockedScopedProxyFactoryBean。虽然目标类最终存在代理,但是在IOC容器中并非是目标类的代理类。
通过上面章节得知,存在@RefreshScope的bean其BeanDefinition中Class属性为FactoryBean类型的class,即LockedScopedProxyFactoryBean。
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();
}
}
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实时获取。
解析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中缓存值。