现在的位置: 首页 > 综合 > 正文

Argo源码阅读(五):Convention

2013年10月08日 ⁄ 综合 ⁄ 共 4388字 ⁄ 字号 评论关闭

ArgoDispatcherFactory.init()中创建了ArgoDispatcher实例,然后再执行ArgoDispatcher的init。以后所有都将交给ArgoDispatcher处理。


            //File ArgoFilter.init()
            dispatcher = ArgoDispatcherFactory.create(servletContext); 
            dispatcher.init();

默认只有ArgoModule,如果自定义了组织级的Module、项目级的Module,则也生成注解器。

public ArgoDispatcher init(ServletContext servletContext, GroupConvention groupConvention) {
	…
        List<Module> modules = Lists.newArrayList();
        modules.add(new ArgoModule(this));


        Module groupModule = groupConvention.group().module();
        if (null != groupModule)
            modules.add(groupModule);

        Module projectModule = groupConvention.currentProject().module();
        if (null != projectModule)
            modules.add(projectModule);

		…
}

groupConvention中的组织指的是com.bj58这种组织,项目指的是HelloWorld这种项目。

GroupConvention包含了组织级的配置接口GroupConfig,以及项目级的配置接口ProjectConfig。

如果要自定义这两个配置,则修改annotatedGroupConventionBinder为对应的类名

    public final static String annotatedGroupConventionBinder = "com.bj58.argo.GroupConventionBinder";

ArgoDipatcherFactor工厂类创建GroupConvention时会根据这个名字创建对应的类,如果是默认的这个不存在的类,则使用默认的DefaultGroupConvention。

	public static GroupConvention getGroupConvention() {

        String className = GroupConvention.annotatedGroupConventionBinder;

        Class<?> clazz = null;
        GroupConvention groupConvention;
        try {
            clazz = GroupConventionFactory.class.getClassLoader().loadClass(className);
            groupConvention = GroupConvention.class.cast(clazz);
        } catch (Exception e) {
            groupConvention = null;
        }

        if (groupConvention != null)
            return groupConvention;

        ...

	return new DefaultGroupConvention(conventionAnnotation, folder);

	}

DefaultGroupConvention添加了@GroupConventionAnnotation注解,查看该注解器接口代码可以看到设置的值包括配置文件夹和日志的目录。

    //GroupConventionAnnotation.java
public @interface GroupConventionAnnotation {

    /**
     * 配置文件夹位置
     *
     * @return 配置文件夹的根目录
     */
    String groupConfigFolder() default "/opt/argo";

    String groupLogFolder() default "{groupConfigFolder}/log";
}

DefaultGroupConvention实现了GroupConvention,因此也包含了GroupConfig和ProjectConfig类型的成员。初始化:

    public DefaultGroupConvention(GroupConventionAnnotation groupConventionAnnotation, File folder) {

        this.folder = folder;

        //根据GroupConventionAnnotation注解中配置的projectConventionClass加载项目级配置类
        ProjectConvention projectConvention = parseProjectConvention(groupConventionAnnotation);

        Map<String, String> configInfoMap = parseGroupConventionPath(groupConventionAnnotation, projectConvention);

        groupConfig = parseGroupConfig(groupConventionAnnotation, configInfoMap);

        //加载项目级配置类,在这里会扫描所有的Controller
        projectConfig = parseProjectConfig(projectConvention, groupConventionAnnotation);

    }

项目配置projectConvention实现了Module接口,并只有一个id成员。

    private ProjectConfig parseProjectConfig(ProjectConvention projectConvention,
                                             GroupConventionAnnotation groupConventionAnnotation) {

        Set<Class<? extends ArgoController>> controllersClasses = parseControllers(groupConventionAnnotation);

        return new DefaultProjectConfig(projectConvention.id(), controllersClasses, projectConvention);

    }

    //扫描所有符合条件的controller
    Set<Class<? extends ArgoController>> parseControllers(GroupConventionAnnotation groupConventionAnnotation) {

        Set<Class<?>> classSet = ClassUtils.getClasses(groupConventionAnnotation.groupPackagesPrefix());

        Pattern controllerPattern = Pattern.compile(groupConventionAnnotation.controllerPattern());

        ImmutableSet.Builder<Class<? extends ArgoController>> builder = ImmutableSet.builder();

        for (Class<?> clazz : classSet)
            if (applyArgoController(clazz, controllerPattern))
                builder
                    .add((Class<? extends ArgoController>) clazz)
                    .build();

        return builder.build();
    }

Group规范的Module如果没有在注解中指定的话,默认是EmptyModule

    private GroupConfig parseGroupConfig(GroupConventionAnnotation groupConventionAnnotation
            , Map<String, String> configInfoMap) {

        String configPath = configInfoMap.get(GROUP_CONFIG_FOLDER);
        String logPath = configInfoMap.get(GROUP_LOG_FOLDER);

        Module module =  EmptyModule.class.isAssignableFrom(groupConventionAnnotation.groupModule())
                ? EmptyModule.instance
                : newInstanceByClass(groupConventionAnnotation.groupModule(), "");

        return new DefaultGroupConfig(getDir(configPath), getDir(logPath), module);

    }

在Argo.init()中将根据以上步骤得到的groupConvention设置相关项

        this.groupConvention = groupConvention;
        this.controllerClasses = groupConvention.currentProject().controllerClasses();

        List<Module> modules = Lists.newArrayList();
        modules.add(new ArgoModule(this));

        Module groupModule = groupConvention.group().module();
        if (null != groupModule)
            modules.add(groupModule);

        Module projectModule = groupConvention.currentProject().module();
        if (null != projectModule)
            modules.add(projectModule);

        servletContext.log("preparing an injector");
        this.injector = buildInjector(modules);
        servletContext.log("injector completed");

通过以上相关步骤,组织级和项目级的Module被添加到Google guice的注解器中。

Convention主要包括约定日志,配置文件目录,定义Module的class。

抱歉!评论已关闭.