我有一个名为菜单的类,注释为 @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();
}
.....
这是GestoreMessaggi类的相关代码
@Component
public class GestoreMessaggi {
@Autowired
private ReloadableResourceBundleMessageSource messageSource;
public void gest(){
messageSource.doSomething() <--- here messageSource is null
}
}
什么时候,我打电话给gestoreMessaggi.gest();从Menu类,我收到一个错误,因为 messageSource 为空。 gestoreMessaggi istance不为null,为null messageSource
重要:只有当我从注释为 @Entity 的类中调用GestoreMessaggi时,才会在messageSource上显示null。
在ds-servlet.xml中,我告诉Spring扫描包含Menu和GestoreMessaggi类的pakages:
//Menu package
<context:component-scan base-package="com.springgestioneerrori.model"/>
//Gestore messaggi package
<context:component-scan base-package="com.springgestioneerrori.internazionalizzazione"/>
谢谢
答案 0 :(得分:6)
您可以采用以下两种方法:
@Entity
类如果你选择选项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扫描这个类才能使它工作。
然后,在@EntityClass
内,执行此操作:
public void setCurrentLanguage(){
GestoreMessaggi gestoreMessaggi = Spring.bean(GestoreMessaggi.class);
gestoreMessaggi.gest();
}
这就是全部。请注意,您无需再将GestoreMessaggi
自动装入@Entity
。另请注意,这种方法既不是Spring也不是大多数社区的推荐,因为它将您的域类(您的@Entity
类)与Spring类耦合。
如果你选择选项2,那么你需要做的就是让Spring像往常一样解决自动装配问题,但在你的实体之外(即在dao或服务中),以及你的实体需要你填写一些消息或其他什么,只需在其上调用一个setter。 (那么您可以根据自己的要求制作@Entity
属性@Transient
。
答案 1 :(得分:2)
Spring上下文不管理实体(通常不管理使用new
实例化的对象),这就是为什么你不能在实体中自动装配bean(来自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 Data 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,你应该在@Service
类中注入(自动装配)你的@Controller
,这样控制器就可以调用调用DAO方法的服务方法来访问你的数据。