Tigase8.0 源代码分析:一、启动篇

发布时间: 5年前 (2020-04-01)浏览: 712评论: 0

转载: https://www.cnblogs.com/eyecool/p/10407041.html

Tigase8.0 引用了IoC(控制反转)和DI(依赖注入) 等技术手段,来对对象的创建和控制。不懂的百度下就知道了,Spring完美的实现IOC ,贴一段解释:

通俗地说:控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。

在Tigase8 中,IOC容器由 Kernel 类实现,Kernel是充当容器管理所有类的依赖对象的注入。

类似Spring 的bean ,在Tigase中,只要是类标有 @Bean(name = "xxx", parent = Kernel.class, active = true)  ,标有Bean注解的类,表明该类的对象创建交由容器负责生成

类属性字段上标有 @Inject(bean = "kernel") 注解时,表明该字段交由容器来赋值

 

Tigase8 中大量使用JAVA8 Function及Stream编程,需要补充基础的同学,可以 https://github.com/CarpenterLee/JavaLambdaInternals 进行学习!

 

下面开始进行代码的粗略讲解,其实 由7到8过渡,核心的架构思想是没有多大变化的,8中只是加入对象的创建管理手段而已,也可以看以前的文章来了解每个组件之间的逻辑关系

入口类 public final class XMPPServer 

 

1
2
3
4
5
6
public static void start(String[] args) {
 ...
 bootstrap = new Bootstrap();
 bootstrap.init(args); //加载配置文件等参数
 bootstrap.start(); //启动系统所有的工作组件进行提供服务
}

  

 

启动包装类 public class Bootstrap
public void start() {
//跳过些次要代码
......
//类加载工具类
classUtilBean = (ClassUtilBean) Class.forName("tigase.util.reflection.ClassUtilBean").newInstance();
//通过查找classpath下的jar,或dir,并且跳过一些过滤的包路径,加载所有的类的Class对象,为后面程序能通过@Bean注解能查找到所有需要容器管理的类
classUtilBean.initialize(ClassUtilBean.getPackagesToSkip(null));
 
// 注册默认类型转换器和属性bean配置器
kernel.registerBean(DefaultTypesConverter.class).exportable().exec();  
                                                                                      
// DSLBeanConfigurator 注册到Kernel的beanInstances中,DSLBeanConfiguratorWithBackwardCompatibility 向下兼容的配置文件管理类,对于Tigase来说非常重要,也就是各种Bean加载的入口
kernel.registerBean(DSLBeanConfiguratorWithBackwardCompatibility.class).exportable().exec();
DSLBeanConfigurator configurator = kernel.getInstance(DSLBeanConfigurator.class);
configurator.setConfigHolder(config);
 
// 加载所有@Bean(name = "message-router", parent = Kernel.class, active = true) Bean中 parent = Kernel.class 的类,并进行注册到Kernel容器中,如下图所示:
configurator.registerBeans(null, null, config.getProperties());
// 启动路由组件的服务
MessageRouter mr = kernel.getInstance("message-router");
mr.start();
}

  

如下图所示,查找标有@Bean注解,并且parent=Kernel.class 的Bean集合的Class,并且进行实例化,注册到Kernel中

 

一、重点来说下 AbstractBeanConfigurator.registerBeans(null, null, config.getProperties()); 加载查找标有@Bean注解,并且parent=Kernel.class 的Bean,注册到Kernel中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void registerBeans(BeanConfig beanConfig, Object bean, Map<String, Object> values) {<br>
//查找标有@Bean注解,并且parent=Kernel.class 的Bean集合
final Map<String, Class<?>> beansFromAnnotations = getBeanClassesFromAnnotations(kernel, beanConfig == null
                                             ? Kernel.class
                                                 : beanConfig.getClazz());<br>
 ....
//遍历所查找到的Bean集合,进行注册到Kernel中
 beansFromAnnotations.forEach((name, cls) -> {
 
 kernel.registerBean(cls)
 .setSource(BeanConfig.Source.annotation)
 .registeredBy(beanConfig)
 .execWithoutInject();<br><br>
 ....
}

  

 

 查找@Bean中parent属性为参数类型的Bean

public static Map<String, Class<?>> getBeanClassesFromAnnotations(Kernel kernel, Class<?> requiredClass) {              
        //从classpath加载到的Class集合中
    Set<Class<?>> classes = ClassUtilBean.getInstance().getAllClasses();                                    
     //遍历这些Class查找出标有@Bean注解,并且parent属性为requiredClass类型的bean Class
    List<Class<?>> toRegister = registerBeansForBeanOfClassGetBeansToRegister(kernel, requiredClass, classes);
        //转换下返回类型
    Map<String, Class<?>> result = new HashMap<>();
    for (Class<?> cls : toRegister) {
        Bean annotation = cls.getAnnotation(Bean.class);
        result.put(annotation.name(), cls);
    }
 
    return result;
}

  

二、启动路由组件的服务,

1
2
3
// 启动路由组件的服务
MessageRouter mr = kernel.getInstance("message-router");
mr.start();

  

在执行getInstance()的时候,对还没初始化的对象进行初始化,进行依赖注入等操作

 

在首次获取Bean实例对象的时候,针对bean对象进行一些配置操作,和依赖注入操作,此后,bean实例才是一个完整的对象,其实和Spring中bean的获取原理是差不多的,不过这里要单纯很多,简单些

1
2
3
4
5
6
7
8
9
10
11
12
protected void initBean(BeanConfig tmpBC, Set<BeanConfig> createdBeansConfig, int deep){
 ....
//构建延迟依赖注入的本地线程队列
  DelayedDependencyInjectionQueue queue = beanConfig.getKernel().beginDependencyDelayedInjection();
 
//针对于初始化的Bean判断是否为系统所默认的配置管理类,如果不是配置管理类本身,则其它类需要调用配置管理类的configure()方法进行配置项处理,如标有@ConfigField的字段
  if (beanConfig.getKernel().isBeanClassRegistered(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME) &&
     !beanConfig.getBeanName().equals(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME)) {
    beanConfigurator = beanConfig.getKernel().getInstance(BeanConfigurator.DEFAULT_CONFIGURATOR_NAME);
   } else {
       beanConfigurator = null;
}<br>....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//如果不是默认配置类,则需要进行配置类的configure方法进行处理
if (beanConfigurator != null) {<br>//此方法会加载@Bean(name = "message-router", parent = beanConfig.clazz.class, active = true),加载@Bean注解中parent为参数beanConfig.clazz类型的Bean,并注册到Kernel中,下面会重点分解:1
    beanConfigurator.configure(beanConfig, bean);
 } else {
 //如果是默认配置类本身,则进行配置类对象的创建和注册到kernel中
   AbstractBeanConfigurator.registerBeansForBeanOfClass(beanConfig.getKernel(), bean.getClass());
}
//这个是线程私有队列,这里进行清理工作
beanConfig.getKernel().finishDependecyDelayedInjection(queue);
 
//这里重点,针对@Bean中所有@Inject注解的字段,进行依赖搜索和依赖注入操作
for (final Dependency dep : beanConfig.getFieldDependencies().values()) {
      beanConfig.getKernel().injectDependencies(bean, dep, createdBeansConfig, deep, false);
}
//如果实现Initializable 接口,则触发.initialize()函数的调用
// there is no need to wait to initialize parent beans, it there any?
if (bean instanceof Initializable && beanConfig.getState() != State.initialized) {
     ((Initializable) bean).initialize();
}
}

  

1、重点谈下 beanConfigurator.configure(beanConfig, bean);

1
2
3
4
5
6
7
8
9
public void configure(BeanConfig beanConfig, Object bean) throws KernelException {
    try {
        grabDefaultConfig(beanConfig, bean);
        Map<String, Object> ccc = getConfiguration(beanConfig);
        configure(beanConfig, bean, ccc);//调用父类的配置方法
    } catch (Exception e) {
        throw new KernelException("Cannot inject configuration to bean " + beanConfig.getBeanName(), e);
    }
}

  

 重点进入父类的configure()方法,查找出@bean注册中parent=beanConfig.clazz类型的Class,进行注册到Kernel容器中

1
2
3
4
5
6
public void AbstractBeanConfigurator.configure(BeanConfig beanConfig, Object bean, Map<String, Object> values) {
........
//查找@Bean中parent属性为参数beanConfig.clazz的类,并加载到Kernel容器中
 registerBeans(beanConfig, bean, values);
.........
}

  

 根据查找到的Bean Class,进行注册,同时涉及到依赖到别的Bean,则判断当前本地线程中是否延迟注入队列,有值,则放到队列中,运行完本操作后,在.finishDependecyDelayedInjection(queue);中完成注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
public void registerBeans(BeanConfig beanConfig, Object bean, Map<String, Object> values) {
        if (beanConfig != null && Kernel.class.isAssignableFrom(beanConfig.getClazz())) {
            return;
        }
            //获得核心的容器管理类
        Kernel kernel = beanConfig == null ? this.getKernel() : beanConfig.getKernel();
        //找出beanConfig.clazz已经注册的Bean,用于取消注册
        Set<String> toUnregister = new ArrayList<>(kernel.getDependencyManager().getBeanConfigs()).stream()
                .filter(bc -> bc.getSource() == BeanConfig.Source.configuration)
                .filter(bc -> beanConfig == null || bc.getRegisteredBy().contains(beanConfig))
                .map(bc -> bc.getBeanName())
                .collect(Collectors.toSet());
                 //遍历classpath中过滤出来的全部Class,查找出标有@Bean注解,并且parent属性为Kernel.class或beanConfig.getClazz()类型的bean Class
        final Map<String, Class<?>> beansFromAnnotations = getBeanClassesFromAnnotations(kernel, beanConfig == null
                                             ? Kernel.class
                                         : beanConfig.getClazz());
            //查找该配置参数中为BeanDefinition的配置项
        final Map<String, BeanDefinition> beanDefinitionsFromConfig =
                values == null ? new HashMap<>() : mergeWithBeansPropertyValue(getBeanDefinitions(values), values);
        ///遍历查找出来的beanConfig.clazz类型子Bean集合,依次进行注册到Kernel容器中
        beansFromAnnotations.forEach((name, cls) -> {
            if (beanDefinitionsFromConfig != null) {
                BeanDefinition definition = beanDefinitionsFromConfig.get(name);
                if (definition != null) {
                    return;
                }
            }
 
            if (isBeanClassRegisteredInParentKernel(kernel.getParent(), name, cls)) {
                return;
            }
 
            BeanConfig bc = kernel.getDependencyManager().getBeanConfig(name);
            if (bc != null && bc.getSource() == BeanConfig.Source.annotation && bc.getClazz().equals(cls)) {
                return;
            }
 
            if (beanConfig != null && beanConfig.getState() == BeanConfig.State.initialized) {
                kernel.registerBean(cls).setSource(BeanConfig.Source.annotation).registeredBy(beanConfig).exec();
            } else {
            //后面要重点讲解下注册,注册到kernel容器中。当注册A对象时,可能会依赖到B对象,所以注册里有使用到本地线程延迟注册队列
                kernel.registerBean(cls)
                        .setSource(BeanConfig.Source.annotation)
                        .registeredBy(beanConfig)
                        .execWithoutInject();
            }
 
            bc = kernel.getDependencyManager().getBeanConfig(name);
            if (bc != null && bc.getState() == BeanConfig.State.inactive && hasDirectConfiguration(bc)) {
                log.log(Level.CONFIG, "bean " + bc.getBeanName() + " is disabled but configuration is specified");
            }
        });
 
                 //根据参数中为BeanDefinition的配置项,查看该Bean是否已经注册,没有则进行注册
        for (BeanDefinition cfg : beanDefinitionsFromConfig.values()) {
            try {
                Class<?> clazz = cfg.getClazzName() == null
                                 ? beansFromAnnotations.get(cfg.getBeanName())
                                 : ModulesManagerImpl.getInstance().forName(cfg.getClazzName());
                BeanConfig oldBc = kernel.getDependencyManager().getBeanConfig(cfg.getBeanName());
                if (clazz == null) {
                    if (bean != null && bean instanceof RegistrarBeanWithDefaultBeanClass) {
                        clazz = ((RegistrarBeanWithDefaultBeanClass) bean).getDefaultBeanClass();
                    } else if (oldBc != null) {
                        clazz = oldBc.getClazz();
                    }
 
                    if (clazz == null) {
                        log.log(Level.WARNING, "unknown class {0} for bean {1}, skipping registration of a bean",
                                new Object[]{cfg.getClazzName(), cfg.getBeanName()});
                        continue;
                    }
                }
 
                if (!tigase.util.reflection.ClassUtilBean.getInstance().getAllClasses().contains(clazz)) {
                    continue;
                }
 
                toUnregister.remove(cfg.getBeanName());
 
                if (oldBc != null && oldBc.getClazz().equals(clazz) &&
                        (oldBc.isExportable() || cfg.isExportable() == oldBc.isExportable())) {
                    kernel.setBeanActive(cfg.getBeanName(), cfg.isActive());
                } else {
                    Bean ba = clazz.getAnnotation(Bean.class);
                    BeanConfigBuilder cfgBuilder = kernel.registerBean(cfg.getBeanName()).asClass(clazz);
                    cfgBuilder.setActive(cfg.isActive()).setSource(BeanConfig.Source.configuration);
                    if (cfg.isExportable()) {
                        cfgBuilder.exportable();
                    }
                    if (ba != null) {
                        if (ba.exportable()) {
                            cfgBuilder.exportable();
                        }
                    }
 
                    cfgBuilder.registeredBy(beanConfig);
 
                    if (beanConfig != null && beanConfig.getState() == BeanConfig.State.initialized) {
                        cfgBuilder.exec();
                    } else {
                        cfgBuilder.execWithoutInject();
                    }
                }
            } catch (ClassNotFoundException ex) {
                log.log(Level.FINER,
                        "could not register bean '" + cfg.getBeanName() + "' as class '" + cfg.getClazzName() +
                                "' is not available", ex);
            }
        }
 
        toUnregister.forEach(beanName -> kernel.unregister(beanName));
    }  

  

  

重点讲解下注册,当执行注册但还没依赖注入的函数。

1
2
3
4
5
6
7
8
9
10
11
12
public BeanConfig BeanConfigBuilder.execWithoutInject() {
        if (beanConfig == null) {
            log.warning("Bean " + clazz +
                                " cannot be registered, because Kernel cannot create configuration for this bean.");
            kernel.currentlyUsedConfigBuilder = null;
            return null;
        }
                //执行bean的注册
        beanConfig = kernel.registerBean(beanConfig, factoryBeanConfig, beanInstance);
 
        return beanConfig;
    }

  

 注册bean实例到Kernel.beanInstances中,bean中所依赖inject的类型,注册到dependencyManager.beanConfigs中,beanConfig通过state来区分,是否为初始化完成的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
protected BeanConfig Kernel.registerBean(BeanConfig beanConfig, BeanConfig factoryBeanConfig, Object beanInstance) {
        BeanConfig parent = null;
        if (beanConfig.getSource() == BeanConfig.Source.annotation && !beanConfig.getRegisteredBy().isEmpty()) {
            BeanConfig bc = dependencyManager.getBeanConfig(beanConfig.getBeanName());
            parent = beanConfig.getRegisteredBy().iterator().next();
            if (bc != null && bc.getClazz().equals(beanConfig.getClazz())) {
                bc.addRegisteredBy(parent);
                parent.addRegisteredBean(bc);
                currentlyUsedConfigBuilder = null;
                return bc;
            }
        }
 
        if (factoryBeanConfig != null) {
            factoryBeanConfig.setPinned(beanConfig.isPinned());
            factoryBeanConfig.setState(beanConfig.getState());
            unregisterInt(factoryBeanConfig.getBeanName());
            dependencyManager.register(factoryBeanConfig);
        }
 
        BeanConfig oldBeanConfig = dependencyManager.getBeanConfig(beanConfig.getBeanName());
        Collection<Dependency> oldDeps =
                oldBeanConfig == null ? null : dependencyManager.getDependenciesTo(oldBeanConfig);
 
        unregisterInt(beanConfig.getBeanName());
                //注册进依赖管理类
        dependencyManager.register(beanConfig);
        if (parent != null) {
            parent.addRegisteredBean(beanConfig);
        }
        //当实例对象不为空,则更新bean的状态为initialized      
        if (beanInstance != null) {
            putBeanInstance(beanConfig, beanInstance);
            beanConfig.setState(State.initialized);
        }
             //查找出本bean可以注入的被依赖集合,简单地说是B 对象内有个依赖注入的A属性,现在beanConfig为A实现类,此时这里就可以查找出B对象这个依赖项包装类Dependency
        Collection<Dependency> deps = dependencyManager.getDependenciesTo(beanConfig);
        if (oldDeps != null) {
            deps.addAll(oldDeps.stream().filter(od -> {
                Field f = od.getField();
                return !deps.stream().anyMatch(nd -> nd.getField().equals(f));
            }).collect(Collectors.toSet()));
        }
 
        currentlyUsedConfigBuilder = null;
        //如果此函数在所在的本地线程内有延迟注入队列,则加入队列,在finishDependecyDelayedInjection(queue);进行给依赖本beanConfig类型的对象,进行依赖注入                                 
        if (!queueForDelayedDependencyInjection(deps)) {<br>                   //当本地线程内无延迟注入队列则为依赖本beanConfig类的对象立即执行依赖注入
           injectDependencies(deps);
        }
 
        return beanConfig;
    }

  前面,我们在 initBean(BeanConfig tmpBC, Set<BeanConfig> createdBeansConfig, int deep) 中有看到 beanConfig.getKernel().finishDependecyDelayedInjection(queue);关于赋值就是在这里进行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private boolean queueForDelayedDependencyInjection(Collection<Dependency> deps) {
            //本地线程队列存在的时候,才会放到队列里去,后面再进行注入
    DelayedDependencyInjectionQueue queue = DELAYED_DEPENDENCY_INJECTION.get();
    if (queue == null) {
        return false;
    }
 
    if (deps.isEmpty()) {
        return true;
    }
 
    queue.offer(new DelayedDependenciesInjection(deps));
    return true;
}

  

 2.举个例子进一步说明下,如MessageRouter中依赖注入componentsAll字段,

1
2
@Inject
private Set<ServerComponent> componentsAll;

  

当调用initBean时,程序针对 componentsAll字段进行依赖注入,当xxx字段有提供setXxx() 的函数时,系统会自动调用该函数。如MessageRouter中提供 setComponentsAll(Set<ServerComponent> components) 函数,所以,当注入componentsAll字段时,会自动调用setComponentsAll函数

 

例如在 MessageRouter 需要注入 componentsAll 组件集合对象,就是在getInstance()时触发的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Bean(name = "message-router", parent = Kernel.class, active = true)
public class MessageRouter ..{
    @Inject
    private Set<ServerComponent> componentsAll;
 
    public void setComponentsAll(Set<ServerComponent> components) {
        if (components == null) {
            return;
        }
 
        HashSet<ServerComponent> removeComponents = new HashSet<>(this.components.values());
        removeComponents.removeAll(components);
        for (ServerComponent comp : removeComponents) {
            if (comp instanceof ComponentRegistrator) {
                removeRegistrator((ComponentRegistrator) comp);
            } else if (comp instanceof MessageReceiver) {
                removeRouter((MessageReceiver) comp);
            } else {
                removeComponent(comp);
            }
            if (comp instanceof ConnectionManager) {
                connectionManagerNames.remove(comp.getName());
            }
            comp.release();
        }
 
        HashSet<ServerComponent> newComponents = new HashSet<>(components);
        newComponents.removeAll(this.components.values());<br>                //这里加载到的组件进行相互注册,通知,和7版本的逻辑是一样的,可以去看以前的文章
        for (ServerComponent comp : newComponents) {
            try {
                if (comp instanceof MessageReceiver) {
                    MessageReceiver mr = (MessageReceiver) comp;
                    mr.setParent(this);
                    mr.start();
                }
                if (comp instanceof ConnectionManager) {
                    connectionManagerNames.add(comp.getName());
                }
                if (comp instanceof ComponentRegistrator) {
                    addRegistrator((ComponentRegistrator) comp);
                } else if (comp instanceof MessageReceiver) {
                    addRouter((MessageReceiver) comp);
                } else {
                    addComponent(comp);
                }
            } catch (ConfigurationException ex) {
                // TODO - most likely this will no longer happen as configuration will not be done in this method
                log.log(Level.WARNING, "component " + comp.getName() + " was not configured properly", ex);
            }
        }
    }
 
}

  

三、最终调用 MessageRouter.start() 启动路由组件进行,路由功能,和7版本的原理是一样,这里就不再一一说明,可以找回以前的文章看

 

到这里启动篇就完成了,Tigase8,看起来代码结构改动大,但是其实也没有多大的变化,核心没有变,变是的包装的架子,所以只要认真地看问题不大,在看源码的同学,建议在调试的时候,再来看这个文章,这样帮助会大些,可以尽可能快地理解Tigase的原理。

如有不对的地方,请提出来,我进行改进!


标签:

上一篇: java队列Queue及阻塞队列
下一篇: Tigase 发送消息的流程源码分析

相关文章暂无相关
评论列表暂无评论
发表评论
验证码

«   2024年4月   »
1234567
891011121314
15161718192021
22232425262728
2930
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
    文章归档
    网站收藏
    友情链接
    • RainbowSoft Studio Z-Blog
    • 订阅本站的 RSS 2.0 新闻聚合
    ︿
    Top