簡體   English   中英

球衣2 + HK2-自動綁定課程

[英]Jersey 2 + HK2 - automatic binding of classess

繼續主題Jersey 2 + HK2-@ApplicationScoped無法正常工作

我已經知道,如何綁定類才能正確@Inject

您有什么想法,如何使這一過程自動化? 在我的應用程序中,將每個服務都放在bind語句中似乎很難聞。

在使用Google的Guice數年之后,我習慣了即時綁定器的可用性,它可以注入任意類型而無需任何前期配置。

我也發現必須顯式綁定每個服務的想法是一種不好的代碼味道。 對於需要使用特殊的構建步驟以及為填充器添加的初始化代碼,我也並不感到瘋狂。

因此,我提出了以下JustInTimeResolver實現:

/**
 * 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;
    }
} 

在我的項目中,我只是將以下內容添加到我的Jersey應用程序配置中的活頁夾中:

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

就像在Guice中一樣,我可以自動創建綁定。

我建議首先在這里查看: 自動服務人口

基本過程是在類上使用@Service批注,並在構建時使用JSR-269(APT)處理器( Metadata Generator )。 這樣做會將一些元數據添加到您的jar文件中(通常在META-INF / hk2-locator / default下)。

然后,您可以使用從每個ServiceLocator中可用的動態配置服務獲得的Populator ,確保自動獲取這些服務,而不必進行所有討厭的綁定。

偽代碼將如下所示:

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等環境中使用。

IMO這是添加服務而不是自己進行所有綁定的更好的方法。

我有一個解決方案,在這里解決了我的問題,我已經嘗試了建議的解決方案,但在這里沒有工作。 在我的解決方案中,必須使用@MyInjectable注釋對每個類進行注釋。

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-創建一個ResourceConfig

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

4-在web.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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM