1

当我的实体被保存时,我一直在寻找一种从服务中调用某些方法的方法。

我的应用程序是使用 roo 1.2.4.RELEASE 创建的

我有一个名为 SaldoCliente 的 Balance 实体和一个名为 AuxCliente 的 ClientAction 实体。

每次持久化新的 ClientAction 实体时,我都需要更新客户端余额。

这是我的代码:

@RooJavaBean
@RooToString
@RooJpaEntity(entityName = "AUX_CLIENTES")
public class AuxCliente {


    @Transient
    @Autowired
    static private SaldoClienteService saldoClienteService;


...


    @PostConstruct
    public void init() 
    {
        System.out.println("Initializing with dependency ["+ saldoClienteService + "]");
    }

    @PostPersist
    private void afectaSaldoCliente(/*Long idTrans, Cliente, Integer cargo, BigDecimal importe, Integer creditos*/) {
      if (saldoClienteService == null) {
          System.out.println("saldoClienteService FUE NULL");
      }
...

我不知道为什么 saldoClienteService 总是为空。

(注意我不希望saldoClienteService在我的数据库中保存一个字段,因此 @Transient 注释)

我一直在寻找没有成功的解决方案。许多解释都是 这样说的,其中说:You need <context:annotation-config/> (or <context:component-scan/>) to enable @PostConstruct handling.

我的 applicationContext.xml 中确实有<context:component-scan>(由 Roo 创建)。

文档说:

默认情况下,将检测 Spring 提供的 @Component、@Repository、@Service 和 @Controller 构造型。注意:这个标签暗示'annotation-config'标签的效果,激活组件类中的@Required、@Autowired、@PostConstruct、@PreDestroy、@Resource、@PersistenceContext 和@PersistenceUnit 注释,这通常是自动检测组件所需要的(无需外部配置)。

至少@Autowired注释在任何地方都有效,但在那里。

有人有一些指示吗?

------------------ 已编辑 ------------------

首先:我要感谢@Sotirios 和@Ralph 花时间帮助我。

如果我从字段中删除“静态”,它是一样的。在我的实体中注入的字段始终为空。(请参阅我在这个问题中的评论,由于“可能”的解决方案,我补充说)。

我在另一个需要注入的课程上也遇到了麻烦。我将它添加到与以前相同的类中(AuxClientes):

@Transient
@Autowired
private ConfigUser configUser;

并且 configUser 也始终为空。

这是其他课程的开始,以防万一。

@RooJavaBean(settersByDefault=false)
public class ConfigUser {
...

当然,在 applicationContext.xml 中:

<bean class="com.i4b.adminctes.util.ConfigUser" id="appConfigUser" />

我在构造函数、服务和存储库中成功使用了 configUser。但不能在实体中使用它。

如果您认为我应该发布代码的任何其他部分,请告诉我。

--------------- 编辑 2 ------------------

我所有的实体也是如此。

--------------- 编辑 3.a ------------------

我更改了问题标题,以获得更好的标题。之前是:

Spring roo(服务自动装配)实体未调用 @PostConstruct 。(将 JPA 存储库与 @RooJpaEntity 一起使用)

--------------- 编辑 3.b ------------------

我刚刚创建了一个最小的测试项目。

// Spring Roo 1.2.4.RELEASE [rev 75337cf] log opened at 2013-11-13 11:36:27
project --topLevelPackage org.example --projectName TestAutowiredOnEntities --java 7 --packaging WAR
jpa setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY 
entity jpa --class ~.domain.MyEntity --testAutomatically --activeRecord false
field string --fieldName text 
repository jpa --interface ~.repository.MyEntityRepository --entity ~.domain.MyEntity
service type --interface ~.service.MyEntityService --entity ~.domain.MyEntity
web mvc setup 
web mvc all --package org.example.web

编辑服务:

package org.example.service;

public class MyEntityServiceImpl implements MyEntityService {

    @Override
    public String testAutowire() {
        return "Some data";
    }
}

编辑实体:

package org.example.domain;
import javax.persistence.PrePersist;
import javax.persistence.Transient;

import org.example.service.MyEntityService;
import org.example.service.MyEntityServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.jpa.entity.RooJpaEntity;
import org.springframework.roo.addon.tostring.RooToString;

@RooJavaBean
@RooToString
@RooJpaEntity
public class MyEntity {

    @Transient
    @Autowired
    MyEntityService myEntityService; 

    /**
     */
    private String text;

    @PrePersist
    public void prePersist() {
        if (myEntityService == null) {
            System.out.println("myEntityService IS NULL");
        } else {
            String data=myEntityService.testAutowire();
            System.out.println("it works: " + data);
            this.text = data;
        }
    } 
}

并编辑 create.jspx 以隐藏服务字段。否则它不会让你保存。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:field="urn:jsptagdir:/WEB-INF/tags/form/fields" xmlns:form="urn:jsptagdir:/WEB-INF/tags/form" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" version="2.0">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <jsp:output omit-xml-declaration="yes"/>
    <form:create id="fc_org_example_domain_MyEntity" modelAttribute="myEntity" path="/myentitys" render="${empty dependencies}" z="T0LoTr6PZAwfIQHkjOZMmPW7cO8=">
        <field:input field="myEntityService" id="c_org_example_domain_MyEntity_myEntityService" render="false" z="12sHnsW2dWYyuD+vDtbTve/jWuI="/>
        <field:input field="text" id="c_org_example_domain_MyEntity_text" z="jUCTnP7E3pYPcZcfGn1tyJ2VeFI="/>
    </form:create>
    <form:dependency dependencies="${dependencies}" id="d_org_example_domain_MyEntity" render="${not empty dependencies}" z="Un0bJ/PmWmczxoVTom9NowwIRWk="/>
</div>

然后执行应用程序并创建一个新的“我的实体”。将字段留空,我按下了保存按钮。

日志显示:

INFO: Reloading Context with name [/testAutowiredOnEntities] is completed
nov 13, 2013 2:31:52 PM org.apache.jasper.compiler.TldLocationsCache tldScanJar
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
myEntityService IS NULL

并且实体有一个空的文本字段。

可以肯定的是,我将@Component 添加到“MyEntity”类中:

...
@Component
@RooJavaBean
@RooToString
@RooJpaEntity
public class MyEntity {
...

没有改变。该服务仍然为空。

我真的希望它可以帮助比我更有知识的人帮助我找到解决方案。

谢谢你们。

同时,我将重新阅读@Ralph 指出的文档部分。我显然做错了什么。我不相信我是唯一需要这个的人。

再次:谢谢大家

4

2 回答 2

0

终于让它工作了。

正如我在对@Ralph 的最后评论中提到的那样:添加@Configurable 注释就可以了。

如果类如下所示,则自动装配有效:

@Configurable                <--- added this
@RooPlural("Tarjetas")
@RooJavaBean
@RooToString
@RooJpaEntity
@Table(name = "TARJETAS")
public class Tarjeta {

    @Autowired
    @Transient
    private ConfigUser configUser;

...

最后我决定使用一个辅助类,以避免 Spring roo 为这个属性生成的所有代码。我不想为 configUser 添加一个私有 getter,以防止 Spring Roo 的公共 getter 存在并在所有脚手架视图中标记 'render="false"'。

我现在有:

@Configurable
@RooJavaBean
public class Helper {

    @Autowired
    private ConfigUser configUser;

    @Autowired
    private SaldoClienteService saldoClienteService;
}

当我需要自动装配的 bean 时,我使用这样的东西:

ConfigUser configUser = new Helper().getConfigUser();

再次:非常感谢@Ralph

于 2013-11-26T12:14:54.747 回答
0

Spring 不会在static字段中注入。

@RooJavaBean
@RooToString
@RooJpaEntity(entityName = "AUX_CLIENTES")
public class AuxCliente {


    @Transient
    @Autowired
    private SaldoClienteService saldoClienteService;

    @PostPersist
    void afectaSaldoCliente() {
       this.saldoClienteService.doWhatYouWant();
    }

}

关于更新#2

它看起来像是ConfigUser一个 Hibernate/JPA/Whatever Entity 但不是 Spring Bean。但是您只能注入 Spring Beans(如 Services、Dao、...(每一个有@Component, @Controller, @Service,@Repository注释的东西*。))

而且您只能注入带有注释的Spring Beans或Classes @Configurable(需要AspectJ)请参阅Spring Reference Chapter 7.8.1 Using AspectJ to dependency injection domain objects with Spring

使用@Configurable是 Spring-Roo 的方式(在您的实体旁边必须有一个文件AuxCliente_Roo_Configurable.aj(在 Eclipse 中,它需要禁用“隐藏生成 Spring Roo ITDs”-过滤器以在包资源管理器中显示此文件))。


* 对象变成spring bean的方式还有很多,不过这里没关系

于 2013-11-11T19:59:39.120 回答