2014-09-24 28 views
13

我需要从singleton获取原型类。我发现方法注入是要走的路,但我真的不知道如何使用spring @Lookup注释。如何使用spring @Lookup注解?

我是新来的依赖注入,我选择了注释配置,所以我想继续这个方向。

我发现@Lookup注释最近才添加(https://spring.io/blog/2014/09/04/spring-framework-4-1-ga-is-here),但我找不到如何使用它。

所以,这里是简化的例子

配置类:

@Configuration 
@Lazy 
public class ApplicationConfiguration implements ApplicationConfigurationInterface { 

    @Bean 
    public MyClass1 myClass1() { 
    return new ContentHolderTabPaneController(); 
    } 

    @Bean 
    @Scope("prototype") 
    public MyClass2 myClass2() { 
    return new SidebarQuickMenuController(); 
    } 
} 

这里是类的例子:

public class MyClass1 { 
    doSomething() { 
    myClass2(); 
    } 

    //I want this method to return MyClass2 prototype 
    public MyClass2 myClass2(){ 
    } 
} 

我如何做,与@Lookup注解?

回答

24

之前将@Lookup注释您public MyClass2 myClass2()方法,@Lookup's Javadoc阅读:

容器将生成方法的通过CGLIB含有类,它是运行时的子类,为什么这样的查询方法只能在豆类的工作,容器通过常规构造函数实例化(例如,查找方法无法从工厂方法返回的bean上替换,我们无法为其动态提供子类)。

所以从ApplicationConfiguration删除以下工厂方法风格Bean声明:

@Bean 
    public MyClass1 myClass1() { 
    return new ContentHolderTabPaneController(); 
    } 

,并添加@Component注解让Spring实例化的bean(也@Lookup添加注释的方法):

@Component 
public class MyClass1 { 
    doSomething() { 
    myClass2(); 
    } 

    //I want this method to return MyClass2 prototype 
    @Lookup 
    public MyClass2 myClass2(){ 
    return null; // This implementation will be overridden by dynamically generated subclass 
    } 
} 

现在得到myClass1 bean取消了上下文,它的myClass2方法应该被替换/重写每次获得一个新的原型bean。


更新

使用工厂方法声明

不难实现@Lookup注释的方法(在 “查找方法”)。如果没有@Lookup并保持你的配置类不变,现在MyClass1样子(其实弹簧产生在子类中有着相似的应用如果使用@Lookup):

public class MyClass1 { 
    doSomething() { 
    myClass2(); 
    } 

    //I want this method to return MyClass2 prototype 
    @Autowired 
    private ApplicationContext applicationContext; 
    public MyClass2 myClass2() { 
     return applicationContext.getBean(MyClass2.class); 
    } 
} 

春天注入了ApplicationContext你。

+0

谢谢。 有没有办法在工厂样式的bean声明中使用MyClass1 Bean作为依赖关系? – Miljac 2014-09-25 11:27:48

+0

然后我们实现我们自己的查找方法 - 幸运的是它非常简单。看到我的更新回答。 – qingbo 2014-09-25 12:27:00

+3

但是这不是DI的这种失败目的,因为Bean实际上必须意识到DI容器? – Miljac 2014-09-25 12:51:08

5

如果你不在春季4。1,您可以使用提供者注入代替:

public class MyClass1 { 
    @Autowired 
    private Provider<MyClass2> myClass2Provider; 

    doSomething() { 
    MyClass2 myClass2 = myClass2(); 
    myClass2.fooBar() 
    } 

    public MyClass2 myClass2(){ 
    return myClass2Provider.get(); 
    } 
} 

这是DI,IoC,避免抽象类和XML查找方法的定义。

+3

'javax.inject.Provider'中,确切地说是 – alaster 2016-10-13 19:32:56

+0

这在我的单元测试中效果很好。我无法让@Lookup工作 – rince 2017-02-01 19:43:59