企业只有建立了自己的网站,做一个手机网站多少钱,谁有网站推荐一下好吗,组成原理毕业设计代做网站推荐文章目录一、源码时序图1. 注册ConfigurationClassPostProcessor流程源码时序图2. 注册ConfigurationAnnotationConfig流程源码时序图3. 实例化流程源码时序图二、源码解析1. 注册ConfigurationClassPostProcessor流程源码解析#xff08;1#xff09;运行案例程序启动类Conf…
文章目录一、源码时序图1. 注册ConfigurationClassPostProcessor流程源码时序图2. 注册ConfigurationAnnotationConfig流程源码时序图3. 实例化流程源码时序图二、源码解析1. 注册ConfigurationClassPostProcessor流程源码解析1运行案例程序启动类ConfigurationAnnotationTest的main()方法2解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?... componentClasses)构造方法3解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext()无参构造方法4解析AnnotatedBeanDefinitionReader类中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)构造方法5解析AnnotatedBeanDefinitionReader类的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)构造方法6解析AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法7解析AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法8解析registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)方法9解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法2. 注册ConfigurationAnnotationConfig流程源码解析1运行案例程序启动类ConfigurationAnnotationTest的main()方法并进入AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?... componentClasses)构造方法。2解析AnnotationConfigApplicationContext类的register(Class?... componentClasses)方法3解析AnnotatedBeanDefinitionReader类的register(Class?... componentClasses)方法4解析AnnotatedBeanDefinitionReader类的registerBean(Class? beanClass)方法5解析AnnotatedBeanDefinitionReader类的doRegisterBean(ClassbeanClass, String name, Class? extends Annotation[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法。6解析BeanDefinitionReaderUtils类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法3. 实例化流程源码解析1运行案例程序启动类ConfigurationAnnotationTest的main()方法并进入AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?... componentClasses)构造方法。2解析AbstractApplicationContext类的refresh()方法3解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法4解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法5解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(Collection? extends BeanFactoryPostProcessor postProcessors, ConfigurableListableBeanFactory beanFactory)方法6解析ConfigurationClassPostProcessor类中的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法7解析ConfigurationClassPostProcessor类的enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法8解析ConfigurationClassEnhancer类的enhance(Class? configClass, ClassLoader classLoader)方法9解析ConfigurationClassEnhancer类的newEnhancer(Class? configSuperClass, ClassLoader classLoader)方法10解析ConfigurationClassEnhancer类的createClass(Enhancer enhancer)方法11解析CALLBACKS12解析BeanMethodInterceptor类13解析BeanMethodInterceptor类的resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName)方法三、总结一、源码时序图 就Configuration注解本身而言在源码层面的执行流程涉及到注册与实例化两种执行流程。 就注册流程而言会涉及到Spring内部的ConfigurationClassPostProcessor类的Bean定义信息的注册流程以及上一篇文章案例中链接标注了Configuration注解的ConfigurationAnnotationConfig配置类的Bean定义信息注册流程。 注意本章的源码时序图和源码解析均以上一章案例程序链接作为入口进行分析并且会在ConfigurationAnnotationConfig类上标注Configuration注解同时在ConfigurationAnnotationTest测试类中调用AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?… componentClasses)构造方法来创建IOC容器。 1. 注册ConfigurationClassPostProcessor流程源码时序图 ConfigurationClassPostProcessor后置处理器是解析Configuration注解的核心类也是Spring中的一个非常重要的后置处理器类 Spring IOC容器启动时会向IOC容器中注册ConfigurationClassPostProcessor类的Bean定义信息。向IOC容器中注册ConfigurationClassPostProcessor类的Bean定义信息的时序图如图所示。 由图可以看出Spring IOC容器启动时向IOC容器中注册ConfigurationClassPostProcessor类的Bean定义信息时会涉及到AnnotationConfigApplicationContext类、AnnotatedBeanDefinitionReader类和AnnotationConfigUtils类中方法的调用。具体源码的调用细节见源码解析部分。 2. 注册ConfigurationAnnotationConfig流程源码时序图 ConfigurationAnnotationConfig类是本章中案例程序的配置类在ConfigurationAnnotationConfig类上标注了Configuration注解当Spring IOC容器启动时也会将ConfigurationAnnotationConfig类的Bean定义信息注册到Spring IOC容器中向Spring IOC容器中注册ConfigurationAnnotationConfig类的Bean定义信息的时序图如图所示。 由图可以看出Spring IOC容器启动时向IOC容器中注册ConfigurationAnnotationConfig类的Bean定义信息时会涉及到AnnotationConfigApplicationContext类、AnnotatedBeanDefinitionReader类、BeanDefinitionReaderUtils类和DefaultListableBeanFactory类的方法调用具体的源码调用细节见源码解析部分。 注意Spring IOC容器在启动时会向IOC容器中注册ConfigurationClassPostProcessor类的bean定义信息和使用Configuration注解标注的ConfigurationAnnotationConfig配置类的Bean定义信息。当Spring IOC容器在刷新时会递归处理所有使用Configuration注解标注的类解析Bean等注解标注的方法解析成一个个ConfigurationClassBeanDefinition类型的BeanDefinition对象注册到IOC容器中。Spring IOC容器刷新时解析Bean等注解的时序图和源码执行流程会在后续章节介绍Bean等注解时详细介绍这里不再赘述。 3. 实例化流程源码时序图 Spring IOC容器在启动过程中最终会调用AnnotationConfigApplicationContext类的refresh()方法刷新IOC容器刷新IOC容器的过程中就会对标注了Configuration注解的配置类进行实例化。本节就结合案例程序简单分析下刷新IOC容器时对标注了Configuration注解的配置类进行实例化的源码时序图源码时序图如图所示。 由图可以看出刷新IOC容器时对标注了Configuration注解的配置类进行实例化时会涉及到AnnotationConfigApplicationContext类、AbstractApplicationContext类、PostProcessorRegistrationDelegate类、ConfigurationClassPostProcessor类和ConfigurationClassEnhancer类方法的调用具体方法调用的细节见源码解析部分。 二、源码解析 本节同样按照注册流程和实例化流程来深入分析Configuration注解在Spring源码层面的执行流程。 1. 注册ConfigurationClassPostProcessor流程源码解析 Configuration注解涉及到ConfigurationClassPostProcessor类的Bean定义信息的注册流程的源码执行过程可结合图1-1进行分析。启动Spring IOC容器时Configuration注解涉及到的ConfigurationClassPostProcessor核心类的注册流程的源码执行过程如下所示。 1运行案例程序启动类ConfigurationAnnotationTest的main()方法
public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(ConfigurationAnnotationConfig.class);//#############省略其他代码##################
}可以看到在main()方法中会调用AnnotationConfigApplicationContext类的构造方法传入配置类ConfigurationAnnotationConfig的Class对象来创建IOC容器。接下来会进入AnnotationConfigApplicationContext类的构造方法。 2解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?… componentClasses)构造方法
public AnnotationConfigApplicationContext(Class?... componentClasses) {this();register(componentClasses);refresh();
}可以看到在上述构造方法中会通过this()调用AnnotationConfigApplicationContext类的无参构造方法。 3解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext()无参构造方法
public AnnotationConfigApplicationContext() {StartupStep createAnnotatedBeanDefReader this.getApplicationStartup().start(spring.context.annotated-bean-reader.create);this.reader new AnnotatedBeanDefinitionReader(this);createAnnotatedBeanDefReader.end();this.scanner new ClassPathBeanDefinitionScanner(this);
}可以看到在AnnotationConfigApplicationContext类的无参构造方法中主要的逻辑就是实例化了AnnotatedBeanDefinitionReader类型的reader成员变量和ClassPathBeanDefinitionScanner类型的scanner成员变量。 reader表示注解类型的Bean定义信息读取器主要就是读取通过注解方式进行实例化的Bean的定义信息。scanner表示类路径下的Bean定义扫描器主要就是扫描类路径下的Bean定义信息。 Configuration注解涉及到的注册流程源码的执行过程会执行实例化reader成员变量的代码也就是下面的代码片段。 this.reader new AnnotatedBeanDefinitionReader(this);接下来会调用AnnotatedBeanDefinitionReader类中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)构造方法。 4解析AnnotatedBeanDefinitionReader类中的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)构造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));
}可以看到在上述构造方法中通过this调用了AnnotatedBeanDefinitionReader类的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)构造方法。 5解析AnnotatedBeanDefinitionReader类的AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)构造方法
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, BeanDefinitionRegistry must not be null);Assert.notNull(environment, Environment must not be null);this.registry registry;this.conditionEvaluator new ConditionEvaluator(registry, environment, null);AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}可以看到在上述构造方法中最核心的逻辑就是调用了AnnotationConfigUtils工具类的registerAnnotationConfigProcessors()方法将BeanDefinitionRegistry类型的registry对象传入方法中。其中registry对象本质上就是一个AnnotationConfigApplicationContext类对象的实例这是因为AnnotationConfigApplicationContext类继承了GenericApplicationContext类而GenericApplicationContext类实现了BeanDefinitionRegistry接口。 6解析AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);
}可以看到在AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry)方法中调用了AnnotationConfigUtils类中的另外一个registerAnnotationConfigProcessors()方法。 7解析AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法 这里只给出在AnnotationConfigUtils类的registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source)方法中将Configuration注解涉及到的ConfigurationClassPostProcessor类的Bean定义信息注册到IOC容器中的核心代码如下所示。 public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME org.springframework.context.annotation.internalConfigurationAnnotationProcessor;public static SetBeanDefinitionHolder registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Nullable Object source) {//################省略其他代码########################if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}//################省略其他代码########################
}可以看到会调用registerPostProcessor()方法注册后置处理器。 8解析registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName)方法
private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(beanName, definition);return new BeanDefinitionHolder(definition, beanName);
}可以看到上述代码中调用了registry参数的registerBeanDefinition()方法来注册ConfigurationClassPostProcessor类的Bean定义信息definition参数本质上就是一个AnnotationConfigApplicationContext类的实例对象。最终会调用DefaultListableBeanFactory类的registerBeanDefinition()方法来注册ConfigurationClassPostProcessor类的Bean定义信息。 9解析DefaultListableBeanFactory类的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法
Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {//##################省略其他代码###############this.beanDefinitionMap.put(beanName, beanDefinition);//##################省略其他代码###############
}通过上述代码可知向Spring的IOC容器中注册类的Bean定义信息其实就是向beanDefinitionMap对象中添加元素beanDefinitionMap对象本质上是一个ConcurrentHashMap对象。向beanDefinitionMap对象中添加的元素的Key为Bean的名称Value为Bean的定义信息。 beanDefinitionMap源码详见 private final MapString, BeanDefinition beanDefinitionMap new ConcurrentHashMap(256);至此Configuration注解涉及到的ConfigurationClassPostProcessor类的注册过程分析完毕。 2. 注册ConfigurationAnnotationConfig流程源码解析 使用Configuration注解标注的ConfigurationAnnotationConfig类的Bean定义信息的注册流程的源码执行过程可结合之前的时序图进行分析启动Spring IOC容器时向IOC容器中注册ConfigurationAnnotationConfig类的Bean定义信息的源码执行过程如下所示。 1运行案例程序启动类ConfigurationAnnotationTest的main()方法并进入AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?… componentClasses)构造方法。
public AnnotationConfigApplicationContext(Class?... componentClasses) {this();register(componentClasses);refresh();
}可以看到在AnnotationConfigApplicationContext(Class?… componentClasses)方法中调用了register()方法传入componentClasses参数进行注册。 2解析AnnotationConfigApplicationContext类的register(Class?… componentClasses)方法
Override
public void register(Class?... componentClasses) {//###########省略其他代码##############this.reader.register(componentClasses);//###########省略其他代码##############
}可以看到在register(Class?… componentClasses)方法中调用了reader的register()方法。 3解析AnnotatedBeanDefinitionReader类的register(Class?… componentClasses)方法
public void register(Class?... componentClasses) {for (Class? componentClass : componentClasses) {registerBean(componentClass);}
}可以看到在register(Class?… componentClasses)方法中会循环遍历传入的可变参数componentClasses每次循环时都会调用registerBean()方法。 4解析AnnotatedBeanDefinitionReader类的registerBean(Class? beanClass)方法
public void registerBean(Class? beanClass) {doRegisterBean(beanClass, null, null, null, null);
}可以看到在registerBean(Class? beanClass)方法中调用了doRegisterBean()方法。 5解析AnnotatedBeanDefinitionReader类的doRegisterBean(ClassbeanClass, String name, Class? extends Annotation[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法。
private T void doRegisterBean(ClassT beanClass, Nullable String name,Nullable Class? extends Annotation[] qualifiers, Nullable SupplierT supplier, Nullable BeanDefinitionCustomizer[] customizers) {AnnotatedGenericBeanDefinition abd new AnnotatedGenericBeanDefinition(beanClass);//###########################省略其他代码#############################String beanName (name ! null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));//###########################省略其他代码#############################BeanDefinitionHolder definitionHolder new BeanDefinitionHolder(abd, beanName);definitionHolder AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}可以看到在doRegisterBean(ClassbeanClass, String name, Class? extends Annotation[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法中调用了BeanDefinitionReaderUtils类的registerBeanDefinition()方法。 6解析BeanDefinitionReaderUtils类的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());//###########################省略其他代码#############################
}可以看到在registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法中通过调用registry的registerBeanDefinition()方法来向IOC容器中注册Bean定义信息。 注意到目前为止后续向IOC容器注册Bean定义信息的源码执行流程与向IOC容器中注册ConfigurationClassPostProcessor类的Bean定义信息的源码执行流程基本相同这里不再赘述。 3. 实例化流程源码解析 Spring IOC容器在刷新时会实例化使用Configuration注解标注的类可结合之前的时序图理解具体的源码执行流程如下所示。 1运行案例程序启动类ConfigurationAnnotationTest的main()方法并进入AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class?… componentClasses)构造方法。
public AnnotationConfigApplicationContext(Class?... componentClasses) {this();register(componentClasses);refresh();
}可以看到在AnnotationConfigApplicationContext(Class?… componentClasses)构造方法中会调用refresh()方法刷新IOC容器。 2解析AbstractApplicationContext类的refresh()方法
Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//#############省略其他代码#####################try {//#############省略其他代码#####################invokeBeanFactoryPostProcessors(beanFactory);//#############省略其他代码#####################}catch (BeansException ex) {//#############省略其他代码#####################}finally {//#############省略其他代码#####################}}
}可以看到在refresh()方法中调用了invokeBeanFactoryPostProcessors()方法。 3解析AbstractApplicationContext类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());//################省略其他代码####################
}可以看到在invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)方法中调用了PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors()方法。 4解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListbeanFactoryPostProcessors)方法
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, ListBeanFactoryPostProcessor beanFactoryPostProcessors) {//#################省略其他代码##################invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//#################省略其他代码##################
}在invokeBeanFactoryPostProcessors()方法中会解析标注了Configuration注解的类中标注了Bean等注解的方法生成相应的Bean定义信息注册到IOC容器中。这里主要关注的是标注了Configuration注解的类的实例化过程所以只需要关注invokeBeanFactoryPostProcessors()方法中的上述代码片段即可。 可以看到在invokeBeanFactoryPostProcessors()方法中又调用了PostProcessorRegistrationDelegate类中的另一个invokeBeanFactoryPostProcessors()方法。 5解析PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors(Collection? extends BeanFactoryPostProcessor postProcessors, ConfigurableListableBeanFactory beanFactory)方法
private static void invokeBeanFactoryPostProcessors(Collection? extends BeanFactoryPostProcessor postProcessors, ConfigurableListableBeanFactory beanFactory) {for (BeanFactoryPostProcessor postProcessor : postProcessors) {StartupStep postProcessBeanFactory beanFactory.getApplicationStartup().start(spring.context.bean-factory.post-process).tag(postProcessor, postProcessor::toString);postProcessor.postProcessBeanFactory(beanFactory);postProcessBeanFactory.end();}
}可以看到在invokeBeanFactoryPostProcessors()方法中会循环遍历传递进来的所有postProcessors集合每次循环时都会使用一个postProcessor对象来接收postProcessors集合中的每一个元素调用postProcessor对象的postProcessBeanFactory()方法并传入beanFactory来实例化对象。 6解析ConfigurationClassPostProcessor类中的postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法
Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {//##############省略其他代码###############enhanceConfigurationClasses(beanFactory);beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}可以看到在postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法中调用了enhanceConfigurationClasses()方法。 7解析ConfigurationClassPostProcessor类的enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {//################省略其他代码########################ConfigurationClassEnhancer enhancer new ConfigurationClassEnhancer();for (Map.EntryString, AbstractBeanDefinition entry : configBeanDefs.entrySet()) {AbstractBeanDefinition beanDef entry.getValue();// If a Configuration class gets proxied, always proxy the target classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// Set enhanced subclass of the user-specified bean classClass? configClass beanDef.getBeanClass();Class? enhancedClass enhancer.enhance(configClass, this.beanClassLoader);if (configClass ! enhancedClass) {//################省略其他代码###################beanDef.setBeanClass(enhancedClass);}}enhanceConfigClasses.tag(classCount, () - String.valueOf(configBeanDefs.keySet().size())).end();
}可以看到在enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法中主要是使用ConfigurationClassEnhancer对象的enhance()方法生成代理类也就是使用CGLib生成代理类。 8解析ConfigurationClassEnhancer类的enhance(Class? configClass, ClassLoader classLoader)方法
public Class? enhance(Class? configClass, Nullable ClassLoader classLoader) {//###################省略其他代码###############Class? enhancedClass createClass(newEnhancer(configClass, classLoader));//###################省略其他代码###############return enhancedClass;
}可以看到在enhance(Class? configClass, ClassLoader classLoader)方法中调用了createClass()方法创建代理类在这之前先调用newEnhancer()方法实例化Enhancer对象。 9解析ConfigurationClassEnhancer类的newEnhancer(Class? configSuperClass, ClassLoader classLoader)方法
private Enhancer newEnhancer(Class? configSuperClass, Nullable ClassLoader classLoader) {Enhancer enhancer new Enhancer();enhancer.setSuperclass(configSuperClass);enhancer.setInterfaces(new Class?[] {EnhancedConfiguration.class});enhancer.setUseFactory(false);enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setAttemptLoad(true);enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));enhancer.setCallbackFilter(CALLBACK_FILTER);enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());return enhancer;
}可以看到newEnhancer()方法中主要是生成CGLib动态代理的Enhancer对象后续会使用Enhancer对象生成代理类。 在newEnhancer()方法中为要生成的代理类设置了父类和接口由于为要生成的代理类设置的接口为EnhancedConfiguration同时EnhancedConfiguration接口继承了BeanFactoryAware接口所以在后续生成的代理类中可以调用BeanFactoryAware接口的setBeanFactory(BeanFactory beanFactory)方法获取到beanFactory对象。 10解析ConfigurationClassEnhancer类的createClass(Enhancer enhancer)方法
private Class? createClass(Enhancer enhancer) {Class? subclass enhancer.createClass();Enhancer.registerStaticCallbacks(subclass, CALLBACKS);return subclass;
}可以看到在createClass(Enhancer enhancer)方法中主要调用了enhancer对象的createClass()方法来创建代理类因为使用CGLib创建出来的代理类是目标类的子类所以这里创建出来的代理类就是目标类的子类。 11解析CALLBACKS 最后再来关注下Enhancer类中传入的CALLBACKS参数。 static final Callback[] CALLBACKS new Callback[] {new BeanMethodInterceptor(),new BeanFactoryAwareMethodInterceptor(),NoOp.INSTANCE
};可以看到CALLBACKS是一个Callback类型的数组数组中的每个元素都是一个Callback类型的对象。其中BeanMethodInterceptor类和BeanFactoryAwareMethodInterceptor类也是拦截器类型。接下来以BeanMethodInterceptor类为例进行介绍。 12解析BeanMethodInterceptor类 BeanMethodInterceptor实现了MethodInterceptor接口和ConditionalCallback接口主要的作用就是对标注了Bean的注解的方法进行拦截执行intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs, MethodProxy cglibMethodProxy)方法生成Bean的实例对象。在方法中有如下一段代码逻辑。 public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,MethodProxy cglibMethodProxy) throws Throwable {// 如果已经创建了Bean的代理实例对象则调用父类的方法。if (isCurrentlyInvokedFactoryMethod(beanMethod)) {//#################省略其他代码###############return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);}return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}上述代码能够保证在类上添加Configuration注解后只会为类生成一个代理对象。也就是说上述代码的逻辑能够保证标注了Configuration注解的类生成的代理类是单例模式的。 因为使用CGLib创建出来的代理类是目标类的子类所以第一次执行上述代码片段时会调用cglibMethodProxy的invokeSuper()方法执行父类的方法也就是执行目标类的方法。第二次执行上述代码片段时会调用resolveBeanReference()方法。 13解析BeanMethodInterceptor类的resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName)方法
private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs, ConfigurableBeanFactory beanFactory, String beanName) {//##############省略其他代码###############boolean alreadyInCreation beanFactory.isCurrentlyInCreation(beanName);try {//##############省略其他代码###############Object beanInstance (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :beanFactory.getBean(beanName));//##############省略其他代码###############return beanInstance;}finally {//##############省略其他代码###############}
}可以看到从resolveBeanReference()方法中会通过beanFactory获取已经初始化好的Bean对象并将这个已经初始化好的bean对象返回。并不会再进行第二次初始化的操作。 所以在类上添加Configuration注解后Spring能够保证为类生成的代理类是单例的。 三、总结 上一章和本章主要对Configuration注解进行了系统性的介绍。首先对Configuration注解进行了简单的说明包括Configuration注解的源码和使用场景以及注意事项。随后给出了Configuration注解的使用案例本章的案例主要是针对使用Configuration注解的一些注意事项给出的案例。接下来详细介绍了Configuration注解在Spring源码层面执行的时序图和对应的源码流程。其中对于注册流程主要介绍了注册ConfigurationClassPostProcessor类后置处理器的Bean定义信息和ConfigurationAnnotationConfig配置类Bean定义信息的注册时序图和源码执行流程。对于实例化流程主要介绍了在Spring IOC容器刷新时实例化ConfigurationAnnotationConfig配置类的代理对象的流程。