(十九)自动装配-Aware接口注入Spring底层组件

结论先行

1。自定义组件如果想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);只需要自定义组件实现xxxAware,并实现相应的方法,在创建对象的时候,Spring会调用接口规定的方法注入相关组件;
2.Spring通过使用xxxAwareProcessor处理实现xxxAware接口想要使用相应的底层组件的bean注入。比如ApplicationContextAware接口就是使用ApplicationContextAwareProcessor处理器处理注入IOC容器

接口定义

/*
 * Copyright 2002-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory;

/**
 * Marker superinterface indicating that a bean is eligible to be
 * notified by the Spring container of a particular framework object
 * through a callback-style method. Actual method signature is
 * determined by individual subinterfaces, but should typically
 * consist of just one void-returning method that accepts a single
 * argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default
 * functionality. Rather, processing must be done explicitly, for example
 * in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
 * for examples of processing {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @since 3.1
 */
public interface Aware {

}

解释

类似与函数回调的方式,让框架可以使用spring的一些bean

接口及其子类

在这里插入图片描述

bean定义

package com.ouyangxizhu;

import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.bean.Red;
import com.ouyangxizhu.config.MainConfigXXXAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTestXXXAware {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigXXXAware.class);
        Red bean = context.getBean(Red.class);
        System.out.println(bean.getApplicationContext() == context);
    }
}

配置类

package com.ouyangxizhu.config;

import com.ouyangxizhu.bean.Red;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MainConfigXXXAware {
    @Bean
    public Red red(){
        return new Red();
    }
}

启动类

package com.ouyangxizhu;

import com.ouyangxizhu.bean.Person;
import com.ouyangxizhu.bean.Red;
import com.ouyangxizhu.config.MainConfigXXXAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTestXXXAware {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfigXXXAware.class);
        Red bean = context.getBean(Red.class);
        System.out.println(bean.getApplicationContext() == context);
    }
}

结果

八月 06, 2020 3:48:08 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Thu Aug 06 15:48:07 CST 2020]; root of context hierarchy
八月 06, 2020 3:48:08 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
当前bean的名字:red
解析的字符串:你好 Mac OS X 我是 121
传入的ioc:org.springframework.context.annotation.AnnotationConfigApplicationContext@31cefde0: startup date [Thu Aug 06 15:48:07 CST 2020]; root of context hierarchy
true

结果说明

通过XXXAware接口,我们可以使用一些Spring的内置bean

原理

在red的setApplicationContext方法打断点,以debug方式运行
可以查看调用栈如下
在这里插入图片描述
1)初始化容器时调用
org.springframework.context.support.AbstractApplicationContext#refresh方法,刷新容器
2)在refres()的12个方法中会调用org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization这个方法,这个方法注释说// Instantiate all remaining (non-lazy-init) singletons.,即初始化其余的非懒加载单例bean
3)上面方法在进行一些beanFactory的检查和beanFactory属性赋值后调用beanFactory的org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons方法,进行真正的始化其余的非懒加载单例bean
4)调用org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)方法获取bean
5)调用org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法,真正获取bean
6)判断是单例bean会尝试 获取单例bean,org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
7)尝试从singletonFactory单例工厂中的缓存获取,如果没有会创建一个新的bean,即singletonObject = singletonFactory.getObject();
org.springframework.beans.factory.ObjectFactory#getObject
8)由于缓存中没有会创建bean。org.springframework.beans.factory.support.AbstractBeanFactory#createBean
9)真正创建bean。org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
10)创建bean之后会调用其初始化方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
11)初始化方法中有下面的片段
1.调用BeanPostProcessors中的BeforeInitialization方法
2.再对bean进行初始化
3.再调用BeanPostProcessorsAfterInitialization

if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

应用BeanPostProcessor的初始化前后方法其实就是获取所有的BeanPostProcessor并调用其相应的初始化前后方法。
12)在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization方法中,会调用org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization这个方法,即调用所有的BeanPostProcessor的postProcessBeforeInitialization方法,注意ApplicationContextAwareProcessor是BeanPostProcessor的实现类
13 在ApplicationContextAwareProcessor中调用org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces这个方法,这个方法如下

private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

即判断bean是否实现了相应接口,实现的话就调用相应的方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值