Java - 通过CDI注入代理

3
在我的项目中,我有一些外部的Java接口(因此我无法更改它们)。 例如:
public interface Abc
{
    void do123();
}

在一个Bean中,我喜欢通过注入来使用这个接口。

例如:

public class TestAbc
{
    @Inject
    private Abc abc;
}

但我没有这个接口的实现或生产方法。相反,我正在寻找一种方法来注入此接口的通用代理。

我猜我需要像CDI扩展这样的东西来做这样的事情。不幸的是,我找不到任何好的如何做的方法。 在一个理想的世界里,我希望可以实现这样的一个方法。

public Object produce( Class< ? > type )
{
    if(isMyType(type))
    {
        // I can produce this type
        return createProxy(type);
    }
    return null; // this method can't produce this type
}

有没有人知道如何做到这一点?

祝好, 约翰内斯


你能详细说明一下吗?如果接口没有实现,你希望注入什么?“代理”会做什么?你总是需要一些实际的实现,所以要么你自己实现它,要么使用其他库。 - Siliarus
@Siliarus 我的想法是,通过Java代理可以“伪造”这个接口。我的具体用例是在客户端中注入EJB RMI接口。对于不同的RMI接口,产品方法看起来总是非常相似。请参见 https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI lookupRemoteStatefulCounter() 。我希望将特定接口所需的参数存储在属性文件中,并将其加载到代理中。 - Johannes
1个回答

3
所以,最终我搞定了。 对于我的用例,我需要一个CDI扩展,它监听ProcessInjectionPoint和AfterBeanDiscovery。 ProcessInjectionPoint收集所有注入相关的接口,AfterBeanDiscovery为这些接口创建bean。
检查注入是否相关是通过一个带有@RMI注释的注释来完成的。@RMI是一种自己的限定符注释。RMILifecyle负责构建或销毁注入对象。 以下是一些源代码。
public class RMIInjectionExtension implements Extension
{
    private Set< Class< ? > > interfaces = Sets.newHashSet();

    void processInjectionPoint( @Observes final ProcessInjectionPoint< ?, ? > aProcessInjectionPoint )
    {
        // collecting all relevant interfaces
        if( aProcessInjectionPoint.getInjectionPoint().getQualifiers().stream()
            .anyMatch( RMI.class::isInstance ) )
        {
            interfaces.add( (Class< ? >)aProcessInjectionPoint.getInjectionPoint().getType() );
        }
    }

    void afterBeanDiscovery( @Observes final AfterBeanDiscovery aAfterBeanDiscovery,
        BeanManager aBeanManager )
    {
        // create beans for the interfaces
        // using DeltaSpike BeanBuilder
        interfaces.stream().map( a -> new BeanBuilder< Object >( aBeanManager ).beanClass( a )
            .qualifiers( (RMI)() -> RMI.class ).beanLifecycle( new RMILifecyle() ).create() )
            .forEach( aAfterBeanDiscovery::addBean );
    }
}

这对我来说很有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接