public abstract class BaseLoaneeRepayment implements Repayment {
@Autowired
protected LoanRepository loanRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public final void repay(RepaymentInfo repaymentInfo) {
Loan loan = loanRepository.lockAndLoad(repaymentInfo.getLoan().id());
}
protected abstract void preCheck(final RepaymentInfo repaymentInfo);
protected abstract void updateLoanee(final RepaymentInfo repaymentInfo);
protected abstract void repayment(final RepaymentInfo repaymentInfo);
protected abstract void calcDifference(final RepaymentInfo repaymentInfo);
}
@Service("loaneeNormalRepayment")
public class NormalRepayment extends BaseLoaneeRepayment implements Repayment {
private static final CatLogger logger = CatLoggerFactory.getLogger(NormalRepayment.class);
@Override
public final void preCheck(RepaymentInfo repaymentInfo) {}
@Override
public final void updateLoanee(RepaymentInfo repaymentInfo) {}
@Override
public final void repayment(RepaymentInfo repaymentInfo) {}
@Override
public final void calcDifference(RepaymentInfo repaymentInfo) {}
}
in Junit,
@TransactionConfiguration(defaultRollback = true)
public class NormalRepaymentTest extends ServiceTest {
@Autowired
@Qualifier("normalRepayment2")
private NormalRepayment normalRepayment;
@Autowired
private LoanService loanService;
@Test
public void test() {
normalRepayment.repay(repaymentInfo);
}
}
This normalRepayment.repay(repaymentInfo);
in NormalRepayment
loanRepository
is null. The autowire not work.
The behavior you see is related to proxies. In certain cases, for Spring managed beans, Spring will create a proxy for the target class. In this case, methods are marked as @Transactional
, and Spring will create a proxy which implements transaction handling for your service. Depending on the proxy strategy, Spring may proxy by subclass , which means a subclass will override methods of the target class and implement various logic such as transaction handling in those methods. In this case, the dependencies will be injected in the proxy, not the target class.
Java, by design, does now allow overriding final methods, and because of this, the proxy subclass will not be able to override the final methods in your concrete class.
The calling code will, in this case, in fact call the non-proxied target methods, where dependencies are not injected and no transactional handling is present.
Solution: Remove the final
modifier from the methods in your concrete class, which will allow Spring to properly proxy your service class.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.