自动assembly不在Class @Entity中工作
我有一个名为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(); } .....
这是GestoreMessaggi类的相关代码
@Component public class GestoreMessaggi { @Autowired private ReloadableResourceBundleMessageSource messageSource; public void gest(){ messageSource.doSomething() <--- here messageSource is null } }
什么时候,我打电话给gestoreMessaggi.gest(); 从Menu类,我收到一个错误,因为messageSource为null。 gestoreMessaggi istance不为null,只为messageSource为null
重要提示 :只有当我从注释为@Entity的类中调用GestoreMessaggi时,才会在messageSource上获取null。
在ds-servlet.xml中,我告诉Spring扫描包含Menu和GestoreMessaggi类的pakages:
//Menu package //Gestore messaggi package
谢谢
您可以采用以下两种方法:
- 尝试从
@Entity
类的方法中获取Spring管理的bean的实例 - 按照@Stijn Geukens的建议更改设计,使您的实体成为POJO,无需任何逻辑或dependency injection机制
如果你选择选项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 bean(Class clazz) { if (context == null) { throw new IllegalStateException(ERR_MSG); } return context.getBean(clazz); } public static 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
自动assembly到@Entity
。 另请注意, Spring和大多数社区都不推荐这种方法 ,因为它将您的域类(您的@Entity
类)与Spring类耦合。
如果你选择选项2,那么你需要做的就是让Spring像往常一样解决自动assembly,但是在你的实体之外 (例如在dao或服务中),如果你的实体需要你填写一些消息或其他什么,只需在其上调用一个setter。 (那取决于您的要求,由您决定@Entity
的属性@Transient
与否)。
Spring上下文不管理实体(通常不管理使用new
实例化的对象),这就是为什么你不能在实体中自动assemblybean(来自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
其他:
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
类中注入(autowire) @Service
,因此控制器可以调用调用DAO方法的服务方法,这些方法访问您的数据。