今天来解释一下在Bean上面加上@Scope注解会发生的事情
ScopedFactoryBean
根据@scope的注解属性,判断是否需要scoped代理
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
// 获取@scope的proxyMode属性
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
// 如果此类不需要代理,默认是不需要的代理的
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
// 如果需要cglib代理
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
// 返回被代理后的beanDefinition
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
具体实现是
org.springframework.aop.scope.ScopedProxyUtils.createScopedProxy()
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
String originalBeanName = definition.getBeanName();
BeanDefinition targetDefinition = definition.getBeanDefinition();
// 生成代理bean的名称,就是在前面加上"scopedTarget"前缀
String targetBeanName = getTargetBeanName(originalBeanName);
// Create a scoped proxy definition for the original bean name,
// "hiding" the target bean in an internal target definition.
// 创建一个scope级别的BeanDefinition
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(targetDefinition.getRole());
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
// 不需要在这里明确的设置,因为默认是true
}
else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
}
// Copy autowire settings from original bean definition.
// 从源bean定义中拷贝自动装配的配置
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
// 是否按照默认的策略进行装配
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
// 拷贝qualifiers的配置
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
// The target bean should be ignored in favor of the scoped proxy.
// 设置源bean在其它bean依赖于它的时候,不被作为一个候选项,因为需要放进去的是一个scoped的代理bean
targetDefinition.setAutowireCandidate(false);
// 当然也不按照默认的策略填充它
targetDefinition.setPrimary(false);
// Register the target bean as separate bean in the factory.
// 注册源beandefine
registry.registerBeanDefinition(targetBeanName, targetDefinition);
// Return the scoped proxy definition as primary bean definition
// (potentially an inner bean).
// 现在返回替换为代理bean的holder
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}
这是BeanDefine实现完成了
在真正的实例化的时候,这个bean会返回一个特殊的代理,
为什么特殊呢,别的代理都是代理同一个bean,但是这个代理牛逼,只是存一下代理的类的信息,每一次都去beanfactory去取。
如果bean的scope是prototype,当然每一次beanfactory都会创建新的bean
如果bean是单例的,当然返回容器缓存的bean。
他是怎么是实现的呢?
在getObject()的时候,从beanfactory去取。。详细看下面源码
org.springframework.aop.scope.ScopedProxyFactoryBean
会先设置BeanFactory
public void setBeanFactory(BeanFactory beanFactory) {
if (!(beanFactory instanceof ConfigurableBeanFactory)) {
throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
}
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
this.scopedTargetSource.setBeanFactory(beanFactory);
ProxyFactory pf = new ProxyFactory();
pf.copyFrom(this);
//这个这个代理Bean设置Bean的来源,很重要。这个方法决定了,
//每次取target的时候,都会调用beanFactory.getBean,所以scope为prototype的时候,可以正确的每一次都是新的实例
// 因为是SimpleBeanTargetSource
pf.setTargetSource(this.scopedTargetSource);
Class<?> beanType = beanFactory.getType(this.targetBeanName);
// 如果工厂里面没有此类的定义
if (beanType == null) {
throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +
"': Target type could not be determined at the time of proxy creation.");
}
// 如果没有强制代理对应class,那么就是代理接口
if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
}
// Add an introduction that implements only the methods on ScopedObject.
// 添加一个只实现ScopedObject这个类的方法的增强
ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));
// AopInfrastructureBean这个interface意味着这个Bean不受自动代理的影响,即便是切点匹配到了它
pf.addInterface(AopInfrastructureBean.class);
this.proxy = pf.getProxy(cbf.getBeanClassLoader());
}
org.springframework.aop.scope.DefaultScopedObject
/**
* 就是这里 ,每一次调用被注入实例的时候都从工厂中获取
* @return 根据scope的类型由工厂是否返回新的实例
*/
@Override
public Object getTargetObject() {
return this.beanFactory.getBean(this.targetBeanName);
}