考虑一下我们有大量由Spring管理的Java DAO类的情况 . 这些bean中定义的每个方法都在Spring的Datasource事务中执行SQL代码,该事务由方法上的注释定义 . 现在我们需要在目标执行所提到的方法之前运行一些自定义代码,这个代码必须在目标方法的注释定义的同一事务中执行 .

根据R4J评论更新:

我的DAO调用代理应该在DAO包中的每个目标调用的事务中调用过程PR_Adm_Set_Usr:

@Aspect
@Order(1000)
@Component
public class DaoProxy {

    private static final Logger logger = LoggerFactory.getLogger(DaoProxy.class);
    @Autowired
    private ContextDAO contextDAO;
    @Autowired
    private DataSourceTransactionManager txManager;


   @Before("execution(* xx.yy.dao.*.*(..)) xx.yy.core.dao.*.*(..))")
    @Transactional(propagation = Propagation.SUPPORTS)
    public void setContext() throws Throwable {
        JdbcTemplate jdbc = new JdbcTemplate(txManager.getDataSource());
        if(SecurityContextHolder.getContext()!=null &&
                SecurityContextHolder.getContext().getAuthentication()!=null &&
                SecurityContextHolder.getContext().getAuthentication().getPrincipal()!=null){
            SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbc)
                    .withProcedureName("PR_Adm_Set_Usr")
                    .withoutProcedureColumnMetaDataAccess().declareParameters(
                            new SqlParameter("user", OracleTypes.VARCHAR));
            jdbcCall.setAccessCallParameterMetaData(false);
            MapSqlParameterSource params = new MapSqlParameterSource()
                    .addValue("user",  SecurityContextHolder.getContext().getAuthentication().getName()  );
            jdbcCall.execute(params);
        }else{
            logger.warn("No context available!!!");
        }
    }
}

SomeDAO类中的DAO调用示例:

@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Object shiftDate(Long fileId, Long interval) {
        String a=null;
        a.toString();
        JdbcTemplate jdbc = new JdbcTemplate(txManager.getDataSource());
        SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbc)
                .withCatalogName("somepackage")
                .withProcedureName("someprocedure")
                .withoutProcedureColumnMetaDataAccess()
                .declareParameters(
                        new SqlParameter("p_file_id", OracleTypes.NUMBER),
                        new SqlParameter("p_interval", OracleTypes.NUMBER)
                );
        jdbcCall.setAccessCallParameterMetaData(false);
        MapSqlParameterSource params = new MapSqlParameterSource()
                .addValue("p_file_id", fileId)
                .addValue("p_interval", interval);
        jdbcCall.execute(params);
        return null;

    }

正如您所看到的,DAO调用中的前两行会导致NullPointerException,这会导致AOP setContext()方法的回滚 . 不幸的是,在我的上下文配置中将订单添加到我的标签之前,这不起作用 .

<tx:annotation-driven order="1"/> 解决了这个问题 .