当前位置: 首页 > 知识库问答 >
问题:

针织2 HK2 -自动装订分类

长孙鸿振
2023-03-14

继续主题泽西岛2 HK2 - @ApplicationScoped不起作用。

我已经知道如何绑定类,以便正确地@Inject它们。

你有什么想法,如何自动化这个过程?在我的应用程序中,将每个服务都放在绑定语句中似乎非常难闻。

共有3个答案

蒋泰
2023-03-14

我有一个建议可以解决我的问题,我已经尝试过提出的解决方案,但在这里不起作用。在我的解决方案中,有必要使用@MyInject table注释来注释每个类。

1-创建注释

@Retention(RUNTIME)
@Target(ElementType.TYPE)
public @interface MyInjectable {
}

2-创建一个AbstractBinder实现

public class MyApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bindFactory(EMFFactory.class).to(EntityManagerFactory.class).in(Singleton.class);
        bindFactory(EMFactory.class).to(EntityManager.class).in(RequestScoped.class);
        bind(Environment.class).to(Environment.class);
        scanAndBind("com.yourpackage.here");
    }

    private void scanAndBind(String packageName) {
        try {
            Class[] classes = getClasses(packageName);
            for (Class<?> klazz:
                 classes) {
                MyInjectable annotation = klazz.getAnnotation(MyInjectable.class);
                if (annotation!= null) {
                    bind(klazz).to(klazz);
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static Class[] getClasses(String packageName)
            throws ClassNotFoundException, IOException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        assert classLoader != null;
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);
        List<File> dirs = new ArrayList<>();
        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            dirs.add(new File(resource.getFile()));
        }
        ArrayList<Class> classes = new ArrayList<Class>();
        for (File directory : dirs) {
            classes.addAll(findClasses(directory, packageName));
        }
        return classes.toArray(new Class[classes.size()]);
    }

    private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
        List<Class> classes = new ArrayList<Class>();
        if (!directory.exists()) {
            return classes;
        }
        File[] files = directory.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                assert !file.getName().contains(".");
                classes.addAll(findClasses(file, packageName + "." + file.getName()));
            } else if (file.getName().endsWith(".class")) {
                classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
            }
        }
        return classes;
    }

}

3-创建资源配置

public class MyApplication extends ResourceConfig {
    @Inject
    public MyApplication(ServiceLocator locator) {
        ServiceLocatorUtilities.enableImmediateScope(locator);
        ....
        register(new MyApplicationBinder());
    }
}

4-在网络中正确配置.xml

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>br.com.solutiontrue.ws</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>your.package.name.MyApplication</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.resource.validation.disable</param-name>
        <param-value>true</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
</servlet>
季小云
2023-03-14

我建议先看这里:自动服务人口。

基本过程是在类上使用@Service注释,并在构建时使用JSR-269(APT)处理器(元数据生成器)。这样做会将一些元数据添加到jar文件中(通常位于META-INF/hk2 locator/default下)。

然后,您可以通过使用从每个ServiceLocator中提供的动态配置服务中获得的填充器,确保这些服务自动获得,而不是必须进行所有那些讨厌的绑定。

伪代码是这样的:

public void populate(ServiceLocator locator) throws Exception {
    DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
    Populator populator = dcs.getPopulator();
    populator.populate(new ClasspathDescriptorFileFinder(getClass().getClassLoader()));
}

在上面的代码中,ClasspathDescriptorFileFinder用于搜索类路径以查找元数据。其他策略可以在OSGi等环境中使用。

在我看来,这是一种添加服务的更好方式,而不是自己做所有的绑定。

夏飞掣
2023-03-14

在使用Google的Guice多年之后,我习惯了即时绑定器的可用性,允许注入任意类型而无需任何前期配置。

我也发现了必须将每个服务显式绑定为糟糕的代码气味的想法。我也不热衷于使用特殊的构建步骤和为填充器添加初始化代码

因此,我想出了以下即时解决方案实现:

/**
 * Mimic GUICE's ability to satisfy injection points automatically,
 * without needing to explicitly bind every class, and without needing
 * to add an extra build step.
 */
@Service
public class JustInTimeServiceResolver implements JustInTimeInjectionResolver {

    @Inject
    private ServiceLocator serviceLocator;

    @Override
    public boolean justInTimeResolution( Injectee injectee ) {
    final Type requiredType = injectee.getRequiredType();

        if ( injectee.getRequiredQualifiers().isEmpty() && requiredType instanceof Class ) {
            final Class<?> requiredClass = (Class<?>) requiredType;

            // IMPORTANT: check the package name, so we don't accidentally preempt other framework JIT resolvers
            if ( requiredClass.getName().startsWith( "com.fastmodel" )) {
                final List<ActiveDescriptor<?>> descriptors = ServiceLocatorUtilities.addClasses( serviceLocator, requiredClass );

                if ( !descriptors.isEmpty() ) {
                    return true;
                }
            }
        }
        return false;
    }
} 

在我的项目中,我只需在我的泽西岛应用程序配置中将以下内容添加到我的活页夹中:

bind( JustInTimeServiceResolver.class ).to( JustInTimeInjectionResolver.class );

然后像在Guice中一样自动创建绑定。

 类似资料:
  • 我正在学习Pharo(Smalltalk实现)课程。关于这门语言,有一个小细节我不太明白。 教授谈到了后期自绑定和静态超级绑定。根据我对静态绑定的理解,编译器在编译时知道我的超级类是什么。这似乎是合乎逻辑的,因为没有多重继承(据我现在所知),所以只能有一个超级。所以它只需要查看继承树并获取父类。 后期自我绑定是我不太理解的东西。在我看来,编译器可以知道它在编译哪个类,所以它知道类型。那么为什么它不

  • 根据我的理解,Java函数指针或lambda,您声明的签名如下所示 为了应用它,我们使用 这里涉及自动装箱吗?如果是,如何避免它(并且仍然有类似于fkt-pointers的东西?) 我知道自动装箱可能是一个性能问题,因为它每次都创建一个对象(而不是堆栈上的一个原语)。如果它隐式地发生,这可能会令人沮丧,所以我问;)

  • 我正在我的web应用程序中使用Jersey starter。 org.springframework.boot spring-boot-starter-jersey 1.4.2.发布 尝试将执行器endpoint集成到应用程序中。使用了以下maven依赖项 org.springframework.boot spring-boot-starter-actor 1.5.2.释放org.springfr

  • 有以下代码: 它打印: 12 这个不能编译。为什么?

  • 主要内容:Spring 自动装配,自动装配规则,示例我们把 Spring 在 Bean 与 Bean 之间建立依赖关系的行为称为“装配”。 Spring 的 IOC 容器虽然功能强大,但它本身不过只是一个空壳而已,它自己并不能独自完成装配工作。需要我们主动将 Bean 放进去,并告诉它 Bean 和 Bean 之间的依赖关系,它才能按照我们的要求完成装配工作。 在前面的学习中,我们都是在 XML 配置中通过 <constructor-arg>和 <

  • 可以通过相对位置把一堆节点放置在一起;最简单的相对摆放方式应该是使用auto-split特性。 两个节点之间的|会把节点分成两部分,然后水平放置在一起 同样,使用||(两个竖线)可以把节点分成两部分,然后把第二个节点放置在第一个节点的下一行。 如果|连接的两个节点中有一个是一个空格组成,那么就会生成一个不可见的节点 如果|连接的两个节点中有一个是超过一个空格组成,那么就会生成一个空节点。 开头和结