本文介绍了DelegatingDataSource Spring启动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为数据源切入点实现Spring Boot AOP-在运行任何查询之前,我需要在数据库连接中设置客户端上下文.

I am trying to implement Spring Boot AOP for data-source pointcut - where before running any query I need to set client context in DB connection.

我正在尝试使用DelegatingDataSource的方法.但是我在服务器启动过程中遇到了错误

I was trying this approach of using DelegatingDataSource. But I am getting below error during server startup

 org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'dataSource': Requested bean is currently in creation: Is there an unresolvable circular reference?

请让我知道DeletegatingDatasource,用于基于JNDI的数据库查找.

Please let me know DeletegatingDatasource for JNDI based DB lookup.

AOP-我试图添加切入点execution(public * javax.sql.DataSource+.getConnection(..)).仅当Spring数据源与用户名/密码一起使用时,此方法才有效.当我使用JNDI在Jboss中部署后,出现WildFlyDataSource代理错误.因此,我想到了使用DelegatingDatasource

Edit 1: AOP - I tried to add pointcut execution(public * javax.sql.DataSource+.getConnection(..)). This works only when Spring datasource is used with username/password. Once i deploy in Jboss with JNDI I am getting WildFlyDataSource Proxy error. So, instead of AOP approach I thought of using DelegatingDatasource

   // AOP Example

    @Pointcut("execution(public * javax.sql.DataSource+.getConnection(..))")
    void prepareConnectionPointcut() {
        logger.debug("prepareConnectionPointcut");
    }

    @AfterReturning(pointcut = "prepareConnectionPointcut()", returning = "connection")
    void afterPrepareConnection(Connection connection) {
        // Set context in Connection - return same connection for query execution
    }

但是当我在JBoss中部署此代码时-我遇到了WildFlyDataSource数据源bean创建错误.

But when i deploy this code in JBoss - I am getting WildFlyDataSource datasource bean creation error.

我还在初始化过程中添加了proxyTargetClass标志

I have also added proxyTargetClass flag during initialization

推荐答案

感谢@ M.Deinum建议使用BeanPostProcessor&实施DelegatingDatasource来设置客户端信息.请找到以下我已实现以实现可以与基于JBoos基于JNDI的连接或Spring Boot URL数据源连接很好地配合.

Thanks @M.Deinum for recommendation of using BeanPostProcessor & Implement DelegatingDatasource for setting client info. Please find snippet below which i have implemented to accomplish this in Spring Boot which works well with JBoos JNDI based connection or Spring Boot URL Datasource connection.

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    private static Logger logger = LoggerFactory.getLogger(MyBeanPostProcessor.class);

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if (bean instanceof DataSource) {
            // Check DataSource bean initialization & enclose it with DelegatingDataSource
            logger.debug("MyBeanPostProcessor:: postProcessAfterInitialization:: DataSource");

            DataSource beanDs = (DataSource) bean;
            return new MyDelegateDS(beanDs);
        }

        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DataSource) {
            logger.debug("MyBeanPostProcessor:: postProcessBeforeInitialization:: DataSource");
        }

        logger.debug("MyBeanPostProcessor:: postProcessBeforeInitialization:: " + beanName);

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

}

我实现的DelegatingDataSource处理每个用户请求,以在数据库连接会话中设置客户端上下文

My implementation of DelegatingDataSource to handle each user request to set client context in DB connection session

 public class MyDelegateDS extends DelegatingDataSource {

    private static Logger logger = LoggerFactory.getLogger(MyDelegateDS.class);

    public MyDelegateDS(DataSource delegate) {
        super(delegate);
        logger.debug("MyDelegateDS:: constructor");
    }

    @Override
    public Connection getConnection() throws SQLException {
        logger.debug("MyDelegateDS:: getConnection");

        // To do this context only for user Request - to avoid this during Server initialization
        if (RequestContextHolder.getRequestAttributes() != null
                && ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest() != null) {

            logger.debug("MyDelegateDS:: getConnection: valid user request");

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();

            // Checking each user request & calling SP to set client context before invoking actual native query/SP
        }

        logger.debug("MyDelegateDS:: getConnection: Not User Request");

        return super.getConnection();
    }

}

希望这对遇到相同问题的人很有帮助

Hope this is helpful for someone facing same problem

这篇关于DelegatingDataSource Spring启动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-30 14:20