自动装配在 Class @Entity 中不起作用
Autowired not working in a Class @Entity
我有一个名为 Menu 的 class,注释为 @Entity,我需要在 @Entity 中使用方法 class 调用了 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();
}
.....
这是class GestoreMessaggi
的相关代码
@Component
public class GestoreMessaggi {
@Autowired
private ReloadableResourceBundleMessageSource messageSource;
public void gest(){
messageSource.doSomething() <--- here messageSource is null
}
}
时,我调用gestoreMessaggi.gest();从菜单 class 中,我得到一个错误,因为 messageSource 为空。 gestoreMessaggi 实例不为空,只是 messageSource
为空
重要:仅当我从注释为 @Entity 的 classes 调用 GestoreMessaggi 时,我才在 messageSource 上得到 null。
在 ds-servlet.xml 我告诉 Spring 扫描包含 Menu 和 GestoreMessaggi 的包 classes:
//Menu package
<context:component-scan base-package="com.springgestioneerrori.model"/>
//Gestore messaggi package
<context:component-scan base-package="com.springgestioneerrori.internazionalizzazione"/>
谢谢
您可以采用两种方法:
- 尝试从您的
@Entity
class 的方法中获取 Spring-managed bean 的实例
- 按照@Stijn Geukens 的建议更改设计,使您的实体成为一个没有任何逻辑或依赖注入机制的 POJO
如果您选择选项 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);
}
}
您需要 Spring 扫描此 class 才能正常工作。
然后,在您的 @EntityClass
中,执行以下操作:
public void setCurrentLanguage(){
GestoreMessaggi gestoreMessaggi = Spring.bean(GestoreMessaggi.class);
gestoreMessaggi.gest();
}
仅此而已。请注意,您不再需要将 GestoreMessaggi
自动连接到您的 @Entity
中。另请注意,Spring 和大多数社区 都不推荐这种方法,因为它与您的域 classes(您的 @Entity
class) 至 Spring classes.
如果您选择选项 2,那么您需要做的就是让 Spring 像往常一样解析自动装配,但是 在您的实体之外(即在dao 或服务),如果您的实体需要您用一些消息或其他内容填充它,只需在其上调用 setter 即可。 (然后由你来决定你的 @Entity
s 属性 @Transient
与否,取决于你的要求)。
Spring 上下文不管理实体(通常不管理使用 new
实例化的对象),这就是为什么你不能自动装配 beans(来自 Spring 的上下文) 在实体中。
最佳实践建议在您的实体中仅保留 getter 和 setter,将业务逻辑留给服务层。
一种常见的方法是Service <-> DAO <-> Entity
。示例:
服务层:
@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 层:
如果你使用Spring数据Jpa:
public interface MenuDao extends JpaRepository<Menu, [menu-id-type]> {}
其他:
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
}
最后记得在配置中配置 Spring 的 bean,包括您的 @Service
和 @Repository
(显式或通过包扫描)。
使用 Spring MVC,您应该在 @Controller
class 中注入(自动装配)您的 @Service
,以便控制器可以调用服务方法,这些方法调用 DAO访问您的数据的方法。
我有一个名为 Menu 的 class,注释为 @Entity,我需要在 @Entity 中使用方法 class 调用了 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();
}
.....
这是class GestoreMessaggi
的相关代码 @Component
public class GestoreMessaggi {
@Autowired
private ReloadableResourceBundleMessageSource messageSource;
public void gest(){
messageSource.doSomething() <--- here messageSource is null
}
}
时,我调用gestoreMessaggi.gest();从菜单 class 中,我得到一个错误,因为 messageSource 为空。 gestoreMessaggi 实例不为空,只是 messageSource
为空重要:仅当我从注释为 @Entity 的 classes 调用 GestoreMessaggi 时,我才在 messageSource 上得到 null。
在 ds-servlet.xml 我告诉 Spring 扫描包含 Menu 和 GestoreMessaggi 的包 classes:
//Menu package
<context:component-scan base-package="com.springgestioneerrori.model"/>
//Gestore messaggi package
<context:component-scan base-package="com.springgestioneerrori.internazionalizzazione"/>
谢谢
您可以采用两种方法:
- 尝试从您的
@Entity
class 的方法中获取 Spring-managed bean 的实例
- 按照@Stijn Geukens 的建议更改设计,使您的实体成为一个没有任何逻辑或依赖注入机制的 POJO
如果您选择选项 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);
}
}
您需要 Spring 扫描此 class 才能正常工作。
然后,在您的 @EntityClass
中,执行以下操作:
public void setCurrentLanguage(){
GestoreMessaggi gestoreMessaggi = Spring.bean(GestoreMessaggi.class);
gestoreMessaggi.gest();
}
仅此而已。请注意,您不再需要将 GestoreMessaggi
自动连接到您的 @Entity
中。另请注意,Spring 和大多数社区 都不推荐这种方法,因为它与您的域 classes(您的 @Entity
class) 至 Spring classes.
如果您选择选项 2,那么您需要做的就是让 Spring 像往常一样解析自动装配,但是 在您的实体之外(即在dao 或服务),如果您的实体需要您用一些消息或其他内容填充它,只需在其上调用 setter 即可。 (然后由你来决定你的 @Entity
s 属性 @Transient
与否,取决于你的要求)。
Spring 上下文不管理实体(通常不管理使用 new
实例化的对象),这就是为什么你不能自动装配 beans(来自 Spring 的上下文) 在实体中。
最佳实践建议在您的实体中仅保留 getter 和 setter,将业务逻辑留给服务层。
一种常见的方法是Service <-> DAO <-> Entity
。示例:
服务层:
@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 层:
如果你使用Spring数据Jpa:
public interface MenuDao extends JpaRepository<Menu, [menu-id-type]> {}
其他:
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
}
最后记得在配置中配置 Spring 的 bean,包括您的 @Service
和 @Repository
(显式或通过包扫描)。
使用 Spring MVC,您应该在 @Controller
class 中注入(自动装配)您的 @Service
,以便控制器可以调用服务方法,这些方法调用 DAO访问您的数据的方法。