春5.xのソース10 invokeBeanFactoryPostProcessors 3件のツアー
BeanFactoryPostProcessor実行処理
治療は治療BeanFactoryPostProcessorインターフェイスを開始する今上であり、また最初の後、BeanDefinitionRegistryPostProcessorインタフェースに対処するための方法の前に話すBeanDefinitionRegistryPostProcessor
カスタム続いて、治療の種類BeanFactoryPostProcessor
、処理の種類。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//BeanDefinitionRegistryPostProcessor的
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);//自定义的BeanFactoryPostProcessor
プロセッサの実行BeanDefinitionRegistryPostProcessorのタイプ
主ConfigurationClassPostProcessor
のpostProcessBeanFactory
カスタムがあり、私たちの主な関心事ですConfigurationClassPostProcessor
。
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
ConfigurationClassPostProcessor的postProcessBeanFactory
強化されたコンフィギュレーションクラスがやって、その後、追加されたImportAwareBeanPostProcessor
ポストプロセッサを。
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {//未注册处理过的
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
//增强配置类
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));//添加后置处理器
}
ConfigurationClassPostProcessor定義された構成豆エキスenhanceConfigurationClasses
まず、構成は、第ますbean
によると、それが取得された定義ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE
クラスは、構成属性である場合に設定される属性full
かlite
。ここでは、カスタムの前にあればことに注意しなければならないBeanDefinitionRegistryPostProcessor
拡張子に作成され、それはプロンプトがあるだろう設定クラスを作成します。
Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);//获取配置属性
MethodMetadata methodMetadata = null;
if (beanDef instanceof AnnotatedBeanDefinition) {
methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();
}
if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
// Configuration class (full or lite) or a configuration-derived @Bean method
// -> resolve bean class at this point...
AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;
if (!abd.hasBeanClass()) {
try {//bean注解的方法设置类加载器
abd.resolveBeanClass(this.beanClassLoader);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
}
}
}//这里就是前面的full 跟 lite的用处了,full可以做增强
if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
if (!(beanDef instanceof AbstractBeanDefinition)) {
throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
}//已经存在单例了,就不能增强了
else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
logger.info("Cannot enhance @Configuration bean definition '" + beanName +
"' since its singleton instance has been created too early. The typical cause " +
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
"return type: Consider declaring such methods as 'static'.");
}
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
if (configBeanDefs.isEmpty()) {//没有要增强的配置bean直接返回
// nothing to enhance -> return immediately
return;
}
強化enhanceConfigurationClassesのConfigurationClassPostProcessor
コンフィギュレーション・クラスのブースターを作成しConfigurationClassEnhancer
、コンフィギュレーション・横断するbean
対象のクラスを取得するために、エージェントの定義をした後、エージェントは強化するために、プロキシクラスを返し、その後、bean
定義しBeanClass
たプロキシクラスの設定を、プロキシクラスの作成の背後に、この時間が作成されます。
ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class设置代理目标类属性
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// Set enhanced subclass of the user-specified bean class
Class<?> configClass = beanDef.getBeanClass();//获取代理的目标类
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);//进行代理
if (configClass != enhancedClass) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +
"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));
}
beanDef.setBeanClass(enhancedClass);//设置为CGLIB动态代理后的类
}
}
エンハンサー充実のConfigurationClassEnhancer
最初のターゲットクラスがないかを決定EnhancedConfiguration
するので、タイプ、および説明があまりにも強化されているので、場合spring
にCGLIB
ターゲットクラスは、実装時に継承強化EnhancedConfiguration
インターフェイスを、実際にあるBeanFactoryAware
インターフェース。それが強化されていなかった場合はnewEnhancer
ブースターを作成し、その後、createClass
強化されたクラスを作成します。
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {//如果已经是EnhancedConfiguration,已经被代理过了
if (logger.isDebugEnabled()) {
logger.debug(String.format("Ignoring request to enhance %s as it has " +
"already been enhanced. This usually indicates that more than one " +
"ConfigurationClassPostProcessor has been registered (e.g. via " +
"<context:annotation-config>). This is harmless, but you may " +
"want check your configuration and remove one CCPP if possible",
configClass.getName()));
}
return configClass;
}
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));//进行动态代理
if (logger.isTraceEnabled()) {
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
configClass.getName(), enhancedClass.getName()));
}
return enhancedClass;
}
newEnhancerのConfigurationClassEnhancerは、インテンシファイアを作成します
これは、CGLIB
あるインターフェース、設定、親クラスを設定するためにブースター、EnhancedConfiguration
次にフィルタ設定生成戦略、セット。
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);//设置父类
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});//设置要实现的接口,就是BeanFactoryAware
enhancer.setUseFactory(false);
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));//生成策略
enhancer.setCallbackFilter(CALLBACK_FILTER);//过滤器拦截器
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());//过滤器类型
return enhancer;
}
CALLBACK_FILTERフィルタ
実際には、インターセプタの一部は、この方法は、それによって強化され、インターセプトを行うために使用しました。
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
private static final ConditionalCallbackFilter CALLBACK_FILTER = new ConditionalCallbackFilter(CALLBACKS);
BeanFactoryAwareGeneratorStrategy生成戦略
それは彼があるなど、このプロパティを生成し、生成されたプロキシクラスに、独自の拡張機能を見るためにバイトコードファイルを生成する方法で$$beanFactory
、その後方法でインターセプターを使用しています。
実際には、それは作ることです具体的には、実装プロセスの参加型アプローチの設定クラスを使用するものだと言うことになります。spring
beanFactory
createClassのConfigurationClassEnhancerは、プロキシクラスを作成します
インスタンスを作成せずに、プロキシクラスを作成し、あるフィルタ、レジスタCGLIB
複合バイトコードを生成する処理を。
private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
// Registering callbacks statically (as opposed to thread-local)
// is critical for usage in an OSGi environment (SPR-5932)...
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);//注册回调
return subclass;
}
私たちは、彼が生成したプロセスの途中見ることができますbeanFactory
:属性バイトコード
をシミュレートするために私たち自身の後者のget 1をspring
使用すると、どのようにcglib
動的プロキシにそれを生成します。
さて、今日ここに、私たちは自分自身の学習、限られた容量を理解し、偉大な神は見スプレーしないで、言い訳してください、助けの調査に希望と理解しています。