2010-05-18 41 views
6

我有了弹簧注入道(下文简化的)一个单:依赖注入到你的单身

public class MyService<T> implements Service<T> { 
    private final Map<String, T> objects; 
    private static MyService instance; 

    MyDao myDao; 

    public void set MyDao(MyDao myDao) { 
     this. myDao = myDao; 
    } 

    private MyService() { 
     this.objects = Collections.synchronizedMap(new HashMap<String, T>()); 
     // start a background thread that runs for ever 
    } 

    public static synchronized MyService getInstance() { 
     if(instance == null) { 
      instance = new MyService(); 
     } 
     return instance; 
    } 

    public void doSomething() { 
     myDao.persist(objects); 
    } 
} 

我的Spring配置可能会是这样的:

<bean id="service" class="MyService" factory-method="getInstance"/> 

但是,这将实例启动期间的MyService。

有没有一种编程方式来执行MyDao到MyService的依赖注入,但没有春天管理MyService?

基本上,我希望能够从我的代码做到这一点:

MyService.getInstance().doSomething(); 

而有弹性注入MyDao我。

回答

2

如果你想要一个singleton,为什么不在Spring配置中定义一个类,并且它自动是一个单例(默认情况下)。

为了避免在启动时初始化,你看过春季lazy initialisation?基本上你需要:

lazy-init="true" 

在你的bean定义中。

+0

你必须在需要的地方使用ApplicationContext获取bean? – Langali 2010-05-18 20:22:31

+0

我会*通常*在初始化时获得我的一个顶级bean,然后根据需要从顶级bean中引用更多的bean。但你可以做你的建议。 – 2010-05-18 20:29:31

0

正如其他人所提到的,你应该让Spring来管理你的单身,但如果你想自己管理他们,只是让春天注入依赖,这样做:

applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService); 
0

我相信FactoryBean接口是一个很好的选择。当你需要执行一些初始化逻辑时,这是一个非常好的选择。例如,要在单独的线程中启动内存数据库或某些后台进程。

您可以在reference documentation中了解更多关于它的信息。

一个演示如何在每次有人想要FactoryBean实现中的bean时实例化数据库并返回数据源的示例。

@PostConstruct 
void init() { 
    embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath) 
     .addScript(dataPath).setType(embeddedDatabaseType).build(); 
} 


public DataSource getObject() throws Exception { 
    return embeddedDatabase; 
} 

这可以实现工厂逻辑和返回对象之间的松散耦合。它在内部被Spring框架大量使用。

如果您希望在第一次使用它时初始化它,请将lazy-initialization设置为true。

如果您希望代码与Spring容器进行交互,另一种方法是创建一个实现了接口ApplicationContextAware的工厂。然后,你可以做这样的事情:

myDao = context.getBean(MyDao.class); 
4

这里是一个解决方案,创建一个类的静态工厂方法:

public class MyService { 
    private static MyService instance; 

    private MyDao myDao; 

    public static MyService createInstance(final MyDao myDao) { 
     instance = new MyService(myDao); 
     return instance; 
    } 

    private MyService(final MyDao myDao) { 
     this.myDao = myDao; 
    } 

    public static synchronized MyService getInstance() { 
     return instance; 
    } 

    public void doSomething() { 
     // just do it! 
     myDao.justDoIt(); 
    } 
} 

,并采用弹簧,用来初始化它:

<bean class="my.path.MyService" factory-method="createInstance" scope="singleton"> 
    <constructor-arg ref="reference.to.myDao" /> 
    </bean> 

现在你应该可以这样做:

MyService.getInstance().doSomething(); 

没有任何问题。