Java 不使用@Inject/@EJB从@Entity访问@Singleton
我正在使用领域驱动设计(我想!),我需要访问一些全局属性。我的@Singleton是这样的:Java 不使用@Inject/@EJB从@Entity访问@Singleton,java,ejb,domain-driven-design,Java,Ejb,Domain Driven Design,我正在使用领域驱动设计(我想!),我需要访问一些全局属性。我的@Singleton是这样的: @Singleton public class MyProperties { private Properties props; @PostConstruct private void initialize() { try { props.load(new FileInputStream("my.properties"));
@Singleton
public class MyProperties {
private Properties props;
@PostConstruct
private void initialize()
{
try {
props.load(new FileInputStream("my.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public String getProperty(String propertyName)
{
return props.getProperty(propertyName);
}
}
我想这样做:
@Entity(name="MYENTITY")
public class MyEntity {
@Inject private MyProperties props;
void doSomething()
{
String myProp = props.getProperty("my-prop");
// ...etc...
}
}
然而,这不起作用-props
是null
,不管怎么说,网站告诉我,我应该这样做,但所有使用JNDI查找的味道都是一样的
我的计划可能是尝试这样的事情:
@WebListener
public class MyServletContextListener implements ServletContextListener{
@Inject private MyProperties props;
private MyServletContextListener theInstance;
@Override
public void contextInitialized(ServletContextEvent sce) {
theInstance = this;
}
static public MyServletContextListener theInstance() { return theInstance; }
public MyProperties getProperties() { return props; }
}
这有意义吗,或者我找错了方向,或者我的代码中有一些愚蠢的错误
编辑:请注意,我使用的是香草JavaEE和CDI、JPA等,没有Spring
EDIT2:我看到CDI的最佳实践表明应该这样做。目前,我的应用程序流控制是从一个
@MessageBean
通过一系列@Entity
s-这是一种设计气味吗?首先,您的任何实体都不在spring应用程序上下文中,因此,spring的任何bean都不能注入到您的实体中!
第二,如果您确实想这样做,请添加:
<context:spring-configured />
在spring配置中,然后在MyEntity类中添加@Configurable 好吧,我找到了我的尊敬的人,并意识到我这里有一个访客模式,它特别有用,因为我的
@实体构成了一个层次结构。因此,我将添加如下代码:
public class DoSomethingVisitor extends EntityVisitor {
@Inject private MyProperties props;
@Override
void visit(MyEntity entity)
{
String myProp = props.getProperty("my-prop");
if(entity.getValue().equals(myProp))
//...or whatever...
}
}
以及:
此解决方案还允许我删除在doSomething()
调用中传递的logger
参数,我的业务逻辑现在已经脱离了@实体
s,进入了一个我可以进行注入的地方。如果您选择javaee方式,我想在这种情况下,在实体上方使用@EntityListener
注释将是首选。它是如何工作的。使用一些带有注释的方法定义侦听器类,例如@PostConstruct
或@PrePersist
:
public class DoSomethingVisitor {
@PrePersist
void visit(MyEntity entity)
{
String myProp = props.getProperty("my-prop");
if(entity.getValue().equals(myProp))
//...or whatever...
}
}
并在实体的注释中定义此类:
@Entity(name="MYENTITY")
@EntityListeners(value = {DoSomethingVisitor.class})
public class MyEntity {
void Accept(EntityVisitor visitor)
{
visitor.visit(this);
}
}
javaee-box中已经包含了所有最好的模式 IMHO从实体访问服务是一种有点笨拙的设计,即数据(实体表示)访问业务逻辑(服务表示)。根据您的需要,我很可能会将逻辑移到服务或将数据存储在实体中,例如,通过引用某种配置实体。顺便说一句,服务定位器模式并不是死的,只是不太需要。:)为什么不听听链接blogpost中给出的建议(不要在实体中注入/用户服务查找)?“全局属性”是应用程序级别的问题。应用程序应该在创建实体或实体的生命周期时,使用相应的值(可能包含在属性文件中)初始化实体。我同意@Thomas的观点,即从实体访问MyProperties
是很尴尬的。请参阅:您可能希望将该注释添加到您的答案中,以便将其保存在一个位置。:)哦,顺便说一句,OP根本没有说他使用了Spring——所以我在这里假设EJB+JPA+CDI,即普通的JavaEE6+。不管是Spring还是EJB,错误根源是:用户的实体不会由Spring或EJB容器管理!这是真的,但如果OP根本不使用Spring,告诉他如何在Spring中实现这一点对他没有帮助。你不能将props
注入DoSomethingVisitor
中,原因与你不能将其注入实体相同。
@Entity(name="MYENTITY")
@EntityListeners(value = {DoSomethingVisitor.class})
public class MyEntity {
void Accept(EntityVisitor visitor)
{
visitor.visit(this);
}
}