一、代理模式种类:
代理模式种类:
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; }}
@RestControllerpublic class PersonController { @Autowired private Person person;}
复制代码
调试看 PersonController 里 person 内容:
ScopedProxyMode.DEFAULT(不添加注解,默认是该模式)
2.ScopedProxyMode.TARGET_CLASS
3.ScopedProxyMode.No(添加该 scope)
评论