Эта статья взята из «Основных принципов Spring 5».
В предыдущем анализе исходного кода мы узнали, что запись внедрения зависимостей (DI) — это метод getBean(), и был пройден основной процесс предыдущей рукописной части IoC. Сначала определите контейнер IoC в GPApplicationContext, а затем сохраните объект GPBeanWrapper на карте. Две карты разработаны в GPApplicationContext: factoryBeanObjectCache сохраняет кеш одноэлементных объектов, factoryBeanInstanceCache сохраняет кеш GPBeanWrapper, а имена переменных также соответствуют родному Spring, Дизайн этих двух объектов на самом деле является классическим приложением зарегистрированного одноэлементного шаблона. .
public class GPApplicationContext extends GPDefaultListableBeanFactory implements GPBeanFactory {
private String [] configLocations;
private GPBeanDefinitionReader reader;
//用来保证注册式单例的容器
private Map<String,Object> factoryBeanObjectCache = new HashMap<String, Object>();
//用来存储所有的被代理过的对象
private Map<String,GPBeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<String, GPBeanWrapper>();
...
}
1 Начните с метода getBean()
Начнем с усовершенствования метода getBean():
@Override
public Object getBean(String beanName) {
GPBeanDefinition beanDefinition = super.beanDefinitionMap.get(beanName);
try{
//生成通知事件
GPBeanPostProcessor beanPostProcessor = new GPBeanPostProcessor();
Object instance = instantiateBean(beanDefinition);
if(null == instance){ return null;}
//在实例初始化以前调用一次
beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
GPBeanWrapper beanWrapper = new GPBeanWrapper(instance);
this.factoryBeanInstanceCache.put(beanName,beanWrapper);
//在实例初始化以后调用一次
beanPostProcessor.postProcessAfterInitialization(instance,beanName);
populateBean(beanName,instance);
//通过这样调用,相当于给我们自己留有了可操作的空间
return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance();
}catch (Exception e){
// e.printStackTrace();
return null;
}
}
2 метод instanceiateBean() для создания экземпляра
//传一个BeanDefinition,就返回一个实例Bean
private Object instantiateBean(GPBeanDefinition beanDefinition){
Object instance = null;
String className = beanDefinition.getBeanClassName();
try{
//因为根据Class才能确定一个类是否有实例
if(this.factoryBeanObjectCache.containsKey(className)){
instance = this.factoryBeanObjectCache.get(className);
}else{
Class<?> clazz = Class.forName(className);
instance = clazz.newInstance();
this.factoryBeanObjectCache.put(beanDefinition.getFactoryBeanName(),instance);
}
return instance;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
3 Метод populateBean() завершает внедрение зависимостей
private void populateBean(String beanName,Object instance){
Class clazz = instance.getClass();
if(!(clazz.isAnnotationPresent(GPController.class) ||
clazz.isAnnotationPresent(GPService.class))){
return;
}
Field [] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(GPAutowired.class)){ continue; }
GPAutowired autowired = field.getAnnotation(GPAutowired.class);
String autowiredBeanName = autowired.value().trim();
if("".equals(autowiredBeanName)){
autowiredBeanName = field.getType().getName();
}
field.setAccessible(true);
try {
field.set(instance,this.factoryBeanInstanceCache.get(autowiredBeanName). getWrappedInstance());
} catch (IllegalAccessException e) {
// e.printStackTrace();
}
}
}
4 постпроцессора GPBeanPostProcessor
BeanPostProcessor в родном Spring — это механизм обратного вызова, установленный для событий инициализации объекта. Эта мини-версия содержит только инструкции, а не конкретную реализацию. Заинтересованные «партнеры» могут продолжить углубленное изучение исходного кода Spring.
package com.tom.spring.formework.beans.config;
public class GPBeanPostProcessor {
//为在Bean的初始化之前提供回调入口
public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
return bean;
}
//为在Bean的初始化之后提供回调入口
public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
return bean;
}
}
До сих пор часть DI была завершена вручную, то есть основная часть Spring была завершена. Обнаружили ли «маленькие друзья», что это на самом деле очень просто?Следуйте «Архитектуре бомбы Тома» и ответьте «Весна», чтобы получить полный исходный код.
Эта статья является оригиналом "Архитектуры бомбы Тома", пожалуйста, указывайте источник при перепечатке. Технология заключается в обмене, я разделяю свое счастье! Если у вас есть какие-либо предложения, вы также можете оставить комментарий или личное сообщение, Ваша поддержка является движущей силой для меня, чтобы упорствовать в создании. Обратите внимание на «архитектуру бомбы Тома», чтобы получить больше технической галантереи!
Нелегко быть оригинальным, и круто настаивать. Вы все это видели здесь. Не забудьте поставить лайк, добавить в закладки, посмотреть и подписаться одним щелчком мыши! Если вы считаете, что контент слишком сух, вы можете поделиться им и отправить своим друзьям, чтобы они питались и питались!