如何自动装配瞬态属性?

How to autowire a transient attribute?

我有一个实体,例如 Employee,它包含一个 @Transient 对象工资,它将派生自相关的 table/Entity DailyTimeRecord (DTR)。 DTR 对象数据检索使用连接,它也在 Employee 对象中自动装配。 DTR 对象列表将作为计算 Salary 对象值的基础。

我在这里 [1]: Why is my Spring @Autowired field null? 发现应该避免使用 new 关键字,让 IoC Container 创建对象。另外,我想避免使用 new 关键字来最小化我的代码的耦合度,并尽可能确保未来的兼容性和支持可扩展性。因此,我有接口 Salary 并由 SalaryImpl class.

实现

但每次我尝试 运行 代码自动装配到瞬态属性 Salary 上时,它始终为空。我在这里找到了根本原因 [2]:How to populate @Transient field in JPA? JPA 中的 Transient 将始终为 null。

我将如何创建一个避免使用 new 关键字的对象,而它是一个瞬态属性?

实体Class

   @Entity
   Class Employee implements Serializable {
          //Attributes from DB here

          @OneToMany
          @JoinColumn(name="empNumber", referencedColumnName = "empNumber")
          private List<DTR> dtr;

          @Autowired
          @Transient
          private Salary salary;

          //getters ang setters here

          public double computeSalary(){

          }
   }

工资界面

   public interface Salary {

          public double computeSalary(List<Benefit> benefits, List<Deduction> deductions);

   }

Base/Implementationclass界面工资

   @Service
   public class SalaryImpl implements Salary, Serializable {

          //other attributes here

          //getter and setters

          //other methods

          @Override
          public double computeSalary(List<Benefit> benefits, List<Deduction> deductions){
                 return 0;
          }
   }

实体对象由 JPA 实现(如 Hibernate)创建,而不由 spring 管理。

它们既不是单例也不是原型,所以一般来说,您不能在实体 bean 的属性上使用自动装配(因为自动装配只能在 spring bean 上完成)。

您可能有兴趣阅读 This SO thread 以获得一些解决方法的想法。

首先,@Transient 来自 JPA,与 Spring 无关。

其次,为了能够让Spring将bean注入EmployeeEmployee也需要注册为spring bean。但实际上,您可以认为 Employee 是由 JPA 实现在幕后使用 "new" 创建的。这就是为什么 spring 无法自动将其他 bean 连接到它。

如果你真的需要这样做,你可以使用 AspectJ 按照 docs.

的描述来做

我个人没有尝试这种方法,因为你可以简单地让你的 SalaryService 接受一个 Employee 作为计算他的薪水的参数之一,这比AspectJ 方法。

public interface SalaryService {
    public double computeSalary(Employee employee , List<Benefit> benefits, List<Deduction> deductions);
} 

客户端代码如下所示:

@Service
public class EmployeeService {

    @Autowired
    private SalaryService salaryService;

    @Transactional
    public void computeEmployeeSalary(Integer employeeId){
        Employee employee = entityManager.find(Employee.class , employeeId);
        salaryService.computeSalary(employee, .... ,.....);
    }

}