java 自动装配在类@Entity 中不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28365154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Autowired not working in a Class @Entity
提问by MDP
I have a class called Menu, annnotated as @Entitywhere i need to use a method inside a class called GestoreMessaggi
我有一个名为Menu的类,注释为@Entity我需要在名为GestoreMessaggi的类中使用一个方法
....
@Component
@Entity
@Table(name="menu")
public class Menu implements Serializable{
@Autowired
@Transient // because i dont' save this field on the DB
private GestoreMessaggi gestoreMessaggi;
.....
public void setCurrentLanguage(){
/* I got the error both if use gestoreMessaggi
this way and if I use the autowired istance of GestoreMessaggi*/
GestoreMessaggi gestoreMessaggi = new GestoreMessaggi();
gestoreMessaggi.gest();
}
.....
This is the relevant code of the class GestoreMessaggi
这是GestoreMessaggi类的相关代码
@Component
public class GestoreMessaggi {
@Autowired
private ReloadableResourceBundleMessageSource messageSource;
public void gest(){
messageSource.doSomething() <--- here messageSource is null
}
}
When, I call gestoreMessaggi.gest(); from Menu class, I got an error because messageSourceis null. The gestoreMessaggi istance is NOT null, is null just messageSource
什么时候,我打电话给 gestoreMessaggi.gest(); 从 Menu 类中,我收到一个错误,因为messageSource为空。gestoreMessaggi istance 不是 null,是 null 只是messageSource
IMPORTANT: I get null on messageSource only when I call GestoreMessaggi from classes annotated as @Entity.
重要提示:只有当我从注释为@Entity 的类中调用 GestoreMessaggi 时,我才会在 messageSource 上获得 null 。
In ds-servlet.xml I tell Spring to scan the pakages that contain Menu and GestoreMessaggi classes:
在 ds-servlet.xml 中,我告诉 Spring 扫描包含 Menu 和 GestoreMessaggi 类的包:
//Menu package
<context:component-scan base-package="com.springgestioneerrori.model"/>
//Gestore messaggi package
<context:component-scan base-package="com.springgestioneerrori.internazionalizzazione"/>
Thank you
谢谢
回答by Federico Peralta Schaffner
You can follow two approaches:
您可以采用两种方法:
- Try to get an instance of a Spring-managed bean from within a method of your
@Entity
class - Change the design as suggested by @Stijn Geukens and make your entity a POJO without any logic or dependency injection machanisms
- 尝试从
@Entity
类的方法中获取 Spring 管理的 bean 的实例 - 按照@Stijn Geukens 的建议更改设计,并使您的实体成为没有任何逻辑或依赖项注入机制的 POJO
If you go by option 1, you have to explicitly access Spring's context and retrieve an instance of the bean you need:
如果选择选项 1,则必须显式访问 Spring 的上下文并检索所需的 bean 实例:
@Component
public class Spring implements ApplicationContextAware {
private static final String ERR_MSG = "Spring utility class not initialized";
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T bean(Class<T> clazz) {
if (context == null) {
throw new IllegalStateException(ERR_MSG);
}
return context.getBean(clazz);
}
public static <T> T bean(String name) {
if (context == null) {
throw new IllegalStateException(ERR_MSG);
}
return (T) context.getBean(name);
}
}
You need to make Spring scan this class in order for this to work.
您需要让 Spring 扫描此类才能使其正常工作。
Then, inside your @EntityClass
, do this:
然后,在您的 中@EntityClass
,执行以下操作:
public void setCurrentLanguage(){
GestoreMessaggi gestoreMessaggi = Spring.bean(GestoreMessaggi.class);
gestoreMessaggi.gest();
}
And that would be all. Note that you wouldn't need to autowire GestoreMessaggi
into your @Entity
any more. Please also note that this approach is not recommended neither by Spring nor by most of the community, since it couples your domain classes (your @Entity
class) to Spring classes.
这就是全部。请注意,您不再需要自动连接GestoreMessaggi
到您的@Entity
。另请注意,Spring 和大多数社区都不推荐这种方法,因为它将域类(您的@Entity
类)与 Spring 类耦合。
If you go by option 2, then all you need to do is let Spring resolve the autowiring as usual, but outside of your entity(i.e. in a dao or service), and if your entity needs you to fill it with some message or whatever, just invoke a setter on it. (Then it's up to you to make your @Entity
s attribute @Transient
or not, depending on your requirements).
如果您选择选项 2,那么您需要做的就是让 Spring 像往常一样解决自动装配,但在您的实体之外(即在 dao 或服务中),并且如果您的实体需要您用一些消息或其他内容填充它,只需在其上调用一个setter。(然后由您决定是否设置@Entity
s 属性@Transient
,具体取决于您的要求)。
回答by Francesco Pitzalis
Spring context does not manage entities (in general does not manage objects instantiated using new
), this is why you cannot autowire beans (that come from Spring's context) in entities.
Spring 上下文不管理实体(通常不管理使用 实例化的对象new
),这就是为什么你不能在实体中自动装配 bean(来自 Spring 的上下文)。
Best practices suggest to keep only getter and setter in your entities, leaving the business logic to the service layer.
最佳实践建议在实体中只保留 getter 和 setter,将业务逻辑留给服务层。
A common approach is Service <-> DAO <-> Entity
. Example:
一种常见的方法是Service <-> DAO <-> Entity
。例子:
Service layer:
服务层:
@Service
public interface GestoreMessaggi {
public void gest();
}
public class GestoreMessaggiImpl implements GestoreMessaggi {
@Autowired
private MenuDao menuDao;
@Override
public void gest() {
// 1) retrieve your entity instance with menuDao
// 2) do stuffs with your entity
// 3) maybe save your entity using menuDao
}
}
DAO layer:
DAO层:
If you use Spring Data Jpa:
如果您使用 Spring Data Jpa:
public interface MenuDao extends JpaRepository<Menu, [menu-id-type]> {}
Else:
别的:
public interface MenuDao {
public Menu findOne([menu-id-type] id);
public Menu save(Menu menu);
// other methods for accessing your data
}
@Repository
public class MenuDaoImpl {
// inject EntityManager or Hibernate SessionFactory
// implement your DAO interface accessing your entities
}
Finally remember to configure Spring's beans including your @Service
s and your @Repository
s in your configuration (explicitly or by package scanning).
最后记得在您的配置中配置 Spring 的 bean,包括您的@Service
s 和您的@Repository
s(显式或通过包扫描)。
Using Spring MVC, you should inject (autowire) your @Service
s in a @Controller
class, so the controller can call services methods, which call DAOs methods, which access your data.
使用 Spring MVC,您应该将您的@Service
s注入(自动装配)到一个@Controller
类中,以便控制器可以调用服务方法,这些方法调用访问您的数据的 DAO 方法。