一、代理模式种类:
代理模式种类:
public enum ScopedProxyMode {
/**
* Default typically equals {@link #NO}, unless a different default
* has been configured at the component-scan instruction level.
*/
DEFAULT,
/**
* Do not create a scoped proxy.
* <p>This proxy-mode is not typically useful when used with a
* non-singleton scoped instance, which should favor the use of the
* {@link #INTERFACES} or {@link #TARGET_CLASS} proxy-modes instead if it
* is to be used as a dependency.
*/
NO,
/**
* Create a JDK dynamic proxy implementing <i>all</i> interfaces exposed by
* the class of the target object.
*/
INTERFACES,
/**
* Create a class-based proxy (uses CGLIB).
*/
TARGET_CLASS;
}
复制代码
二、代理模式的处理
public class AnnotationConfigUtils {
//应用代理模式
static BeanDefinitionHolder applyScopedProxyMode(ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
//不用代理,直接返回
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
//是否使用cglib代理
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
}
class ScopedProxyCreator {
ScopedProxyCreator() {
}
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
public static String getTargetBeanName(String originalBeanName) {
return ScopedProxyUtils.getTargetBeanName(originalBeanName);
}
}
public abstract class ScopedProxyUtils {
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
//将该definition重新定义一个代理的definition,并注入到该beanFactory
}
}
复制代码
创建代理的过程:
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition 开始赋值
初始化: sourceDefinition=definition.getBeanDefinition(); sourceBeanName=definition.getBeanName(); proxyBeanName = getTargetBeanName(originalBeanName);
设置装饰 bean: setDecoratedDefinition(new BeanDefinitionHolder(sourceDefinition, proxyBeanName));
设置原始 bean: setOriginatingBeanDefinition(sourceDefinition);
设置 source:setSource(definition.getSource());
设置 role: setRole(sourceDefinition.getRole());
添加属性值: targetBeanName=proxyBeanName; proxyTargetClass= isProxy;
设置是否自动注入: setAutowireCandidate(sourceDefinition.isAutowireCandidate())
设置是否主: setPrimary(sourceDefinition.isPrimary());
如果是抽象 bean 对象,copy 需要自动注入的属性值 copyQualifiersFrom((AbstractBeanDefinition) sourceDefinition);
修改 sourceDefinition 部分属性值:
sourceDefinition.setAutowireCandidate(false);
sourceDefinition.setPrimary(false);
将 definition 注入到当前的 beanFactory(proxyBeanName, sourceDefinition)
创建新的 BeanDefinitionHolder,并返回。
new BeanDefinitionHolder(proxyDefinition, sourceBeanName, definition.getAliases());
todo: 为啥要这么搞呢?目的是什么?
三、代理模式处理过程的调用场景:
场景一、通过 ScopedProxyUtils 调用(基本属于内部调用,忽略)
场景二、ScopedProxyBeanDefinitionDecorator 主要是被 AopNamespaceHandler 调用
日常 aop 使用场景
场景三、通过 ScopedProxyCreator 调用
场景四:通过 AnnotationConfigUtils 调用
主要是 component 等注解 bean
场景五:ConfigurationClassBeanDefinitionReader 调用:主要是加载 beanMethods 注解
class ConfigurationClassBeanDefinitionReader {
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS);
beanDefToRegister = new ConfigurationClassBeanDefinition(
(RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
}
}
}
复制代码
转化为流程图:
最下面几个就是加载 bean 注解相关的类
四、代码样例直观感受
@Configuration
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@RestController
public class PersonController {
@Autowired
private Person person;
}
复制代码
调试看 PersonController 里 person 内容:
ScopedProxyMode.DEFAULT(不添加注解,默认是该模式)
2.ScopedProxyMode.TARGET_CLASS
3.ScopedProxyMode.No(添加该 scope)
评论