前言
上一篇我们讲解了包实例化的前期准备工作,创建缓存,构建体系,移入准备,移除准备。这篇来处理后置处理器的注入和实例的生成
构建后置处理器体系
换个思路讲解,我们开始进入refresh()刷新容器中,第一步创建工厂,第二步注册后置处理器
第一部分代码:关于如何获取到后置处理器的派生类,如何拿到实例放入缓存
@Override
public void refresh() {
synchronized (startupShutdownMonitor) {
// 创建工厂对象
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//注册后置处理器
registerBeanPostProcessors(beanFactory);
// 实例化所有单例作用域(Singleton)Bean定义的实例
finishBeanFactoryInitialization(beanFactory);
}
}
private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//委托类,委托类负责注入
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
委托类的实现
/**
* 后置处理的注册委托类
*/
public class PostProcessorRegistrationDelegate {
/**
* 构建后置处理器
* @param beanFactory
* @param abstractApplicationContext
*/
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext abstractApplicationContext){
// 获取所有关于BeanPostProcessor类型的beanName集合
//传入主类,传入是否包含单列,传入是否费及时加载
//下面有getBeanNamesForType方法详解
String[] postProcessorNames = beanFactory
.getBeanNamesForType(BeanPostProcessor.class, true, false);
Set<BeanPostProcessor> postProcessors = new HashSet<>();
//再遍历集合从工厂中拿到实例的集合
for (String postProcessorName : postProcessorNames) {
// 获取后期处理名称对应实例
BeanPostProcessor postProcessor = beanFactory.getBean(postProcessorName, BeanPostProcessor.class);
// 把生成后置处理器的实例放入集合中
postProcessors.add(postProcessor);
}
// 注册所有的BeanPostProcessor实例
registerBeanPostProcessors(beanFactory, postProcessors);
}
/**
* 注册所有的BeanPostProcessor实例放进工厂
* @param beanFactory
*/
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, Set<BeanPostProcessor> postProcessors){
for (BeanPostProcessor postProcessor : postProcessors) {
//放入工厂
beanFactory.addBeanPostProcessor(postProcessor);
}
}
}
getBeanNamesForType
获取关于是否是当前类的派生类,如果是则存入集合
/**
* 获取所有派生类的BeanName
* @param type
* @param includeNonSingletons
* @param allowEagerInit
* @return
*/
@Override
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
Set<String> beanNameSet = new LinkedHashSet<>();
beanDefinitionMap.forEach((beanName,beanDefinition)->{
Class<?> aClass = beanDefinition.getbeanClass();
//判断是不是派生类
if (type.isAssignableFrom(aClass)) {
//是则拿到集合
beanNameSet.add(beanName);
}
});
return beanNameSet.toArray(new String[0]);
}
addBeanPostProcessor
添加进缓存集合,beanPostProcessors
是个线程安全集合
/** BeanPostProcessors to apply in createBean. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
// Remove from old position,
//先移除掉,保证集合里是最新的后置处理器
this.beanPostProcessors.remove(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
this.beanPostProcessors.add(beanPostProcessor);
}
第二部分,原始后置处理器注入
注入原生后置处理器
//internalAutowiredAnnotationProcessor后置处理器地址
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
/**
* 注册默认的注解解析后置处理器
* @param registry
* @param source
*/
public static void registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, Object source) {
if
//检查是否包含注册体系
(!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
//将对象注入工厂
registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
}
}
private static void registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
registry.registerBeanDefinition(beanName, definition);
}
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
//将后置处理器放入集合当中
synchronized (monitor){
if (!beanDefinitionMap.containsKey(beanName)){
beanDefinitionMap.put(beanName,beanDefinition);
this.beanDefinitionNames.add(beanName);
}
}
}
第三部分,依赖注入实例化
思路,反射寻找到所有字段,遍历字段集合,寻找标注了注解的字段,
找到后根据类型和名字进行匹配,匹配到后,找到getBean获取类型实例。
核心代码
/**
* 开始处理对象依赖注入(只提供字段注入)
* @param bean
* @param beanName
* 装配规则:
* 1、首先按照类型装配,如果只有一个符合bean就直接注入
* 2、如果发现有多个同类型的实例,就按照名称装配
*/
@Override
public void postProcessProperties(Object bean, String beanName) {
//找到依赖注入的字段属性集合
//只提供字段的注入
//找到需要装配的字段
List<Field> injectFields = findAutowiringMetadata(bean, beanName);
if (injectFields.size() == 0) {
return;
}
/**
* 装配规则
* 1.首先按类型装配,如果只有一个符合的类型直接装配
* 2.如果有多个相同的类型按名称装配
*/
for (Field injectField : injectFields) {
Object injectInstance = null;
// 获取注入的字段类型
Class<?> type = injectField.getType();
String[] names = beanFactory.getBeanNamesForType(type, true, false);
if (names!= null && names.length == 1) {
// 如果这个类型只有一个
injectInstance = beanFactory.getBean(names[0]);
} else if (names != null && names.length > 1){
// 如果发现类型有多个,只能按照名称装配
for (String name : names) {
if (name.equals(injectField.getName())) {
injectInstance = beanFactory.getBean(name);
break;
}
}
}
try {
// 使用反射设置当前bean对应依赖对象的值
injectField.setAccessible(true);
injectField.set(bean, injectInstance);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
在上面的核心代码中beanFactory.getBean(names[0]);
其实就是dogetBean里面的从三级缓存里拿对象,包括我们对外暴露的其实也是从三级缓存里拿,如果有直接返回Bean没有则去构建
findAutowiringMetadata
找到需要装配的字段
private final Map<String, List<Field>> injectionFieldCache = new ConcurrentHashMap<>(256);
/**
* 寻找包含autowired的字段属性
* @param bean
* @param beanName
* @return
*/
private List<Field> findAutowiringMetadata(Object bean, String beanName) {
List<Field> fields = this.injectionFieldCache.get(beanName);
//如果需要获取的字段为空则进入进行寻找需要生成的字段,如果存在则直接返回
if (fields==null){
fields=new ArrayList<>();
for (Class<? extends Annotation> autowiredAnnotationType : autowiredAnnotationTypes) {
// 获取当前bean对应
Field[] declaredFields = bean.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
//判断是否包含autowired这个注解
if (declaredField.isAnnotationPresent(autowiredAnnotationType)) {
fields.add(declaredField);
}
}
//把需要生成的字段属性放入map集合,
this.injectionFieldCache.put(beanName, fields);
}
}
return fields;
}
doGetBean核心代码
protected <T> T doGetBean(final String beanName,final Class<T> requiredType,
final Object[] args, boolean typeCheckOnly) {
Object bean = null;
/**
* 获取缓存中存储的与当前beanName对应实例
* private Object getObjectForBeanInstance(Object sharedInstance, String beanName, Object o) {
* // 扩展基于FactoryBean实例方式
* return sharedInstance;
* }
*/
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//源代码这里是工厂实例化校验我们直接返回Bean就行
bean = getObjectForBeanInstance(sharedInstance, beanName, null);
}
else {
if (!typeCheckOnly) {
//标记当前BeanName正在被构建
markBeanAsCreated(beanName);
}
try {
//通过BeanName拿到对象包装为RootBeanDefinition,RootBeanDefinition为需要注入的单例Bean类型
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 根据bean定义作用域类型来创建实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//创建Bean
return createBean(beanName, mbd, args);
} catch (Exception ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
//如果出现了异常需要把校验缓存移除掉
destroySingleton(beanName);
throw ex;
}
});
//源代码这里是工厂实例化校验我们直接返回Bean就行
bean = getObjectForBeanInstance(sharedInstance, beanName, mbd);
} else if (mbd.isPrototype()) {
//是否多列,这里我们不写,只写主流单列
}
} catch (Exception e) {
e.printStackTrace();
}
if (requiredType != null) {
// 判断获取的类型是否与需求类型一致
if (!requiredType.isAssignableFrom(bean.getClass())) {
throw new RuntimeException("创建的类型与期望类型不一致");
}
}
}
return (T) bean;
}
单列Bean的实现
///注入单列Bean
protected Object initializeBean(String beanName, Object exposedObject, RootBeanDefinition mbd){
if (exposedObject instanceof Aware) {
// 判断是否为某个具体扩展接口
if (exposedObject instanceof BeanFactoryAware) {
// 回调对应实现类中setBeanFactory方法
((BeanFactoryAware) exposedObject).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
return exposedObject;
};
setBeanFactory
方法是给将现在已经有了缓存抽象工厂对象重新赋值给属性。
测试
成功输出了依赖对象Dao中的hello方法
感悟
对于构建感悟
好像没有什么重点需要提及到了,整个代码花了我一周半的时间,大部分时间都花在阅读上了,我如果有读者连续读就应该发现了我每一篇讲述的方法都不一样,因为越到很面很多类的方法交叉,实在不好用文章这样线性的方法讲述出来,只好写出关键代码,重要的流程,一些warpper,rootbeandinition这样的特定下的特定封装类我就没编写了,这样的类也有自己接口体系,实在复杂,不过主线清楚了其他就是旁门左道。
对于Spring感悟
其实Spring的核心其实也是一些基础流程+设计模式,工厂设计模式,代理设计模式,模板设计模式,还有一些设计巧妙的地方。
基础流程,就我们在只有路径的情况下,根据现有条件如何去解析文件,去寻找我们符合条件的文件,比如类路径解析路径下的所有文件,有了文件解析类的特征元数据,再按一定规则去设置元数据的值,再根据元数据的值去包装这个文件,包装成符合需求特征的文件进行处理,几乎所有都是这样的思想进行下去的。
对于整个框架单一职责是体会最深刻的,很多明明可以自己完成的但是也要明确给别人,哪怕没有继承关系,也要通过继承相同接口,交由别人实现。
后续会再读几次吧。
百度云:https://pan.baidu.com/s/1ZnCLzItaXjIbTcnLEg0iaw
密码:gfe8