我有一个弹簧注射Dao的单身人士(简化如下):
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);
}
}
我的春季配置可能如下所示:
<bean id="service" class="MyService" factory-method="getInstance"/>
但是这会在启动时实例化MyService。
是否有一种编程方式将MyDao依赖注入MyService,但没有spring管理MyService?
基本上我希望能够从我的代码中执行此操作:
MyService.getInstance().doSomething();
春天为我注射了MyDao。
答案 0 :(得分: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();
}
}
并使用spring来启动它:
<bean class="my.path.MyService" factory-method="createInstance" scope="singleton">
<constructor-arg ref="reference.to.myDao" />
</bean>
现在你应该能够做到:
MyService.getInstance().doSomething();
没有任何问题。
答案 1 :(得分:2)
如果你想要一个单例,为什么不在Spring配置中定义一个类,它自动是一个单独的(默认情况下)。
为了避免在启动时初始化,你看过Spring lazy initialisation吗?基本上你需要:
lazy-init="true"
在你的bean定义中。
答案 2 :(得分:0)
正如其他人所提到的,你应该让spring管理你的单身人士,但如果你想自己管理它们并让spring注入依赖关系,那就这样做:
applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService);
答案 3 :(得分: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);