委托数据源 Spring boot

问题描述 投票:0回答:2

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

我正在尝试使用 DelegatingDataSource 的this方法。但我在服务器启动期间遇到以下错误

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

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

编辑 1:AOP - 我尝试添加切入点

execution(public * javax.sql.DataSource+.getConnection(..))
。仅当 Spring 数据源与用户名/密码一起使用时,这才有效。一旦我使用 JNDI 部署在 Jboss 中,我就会收到
WildFlyDataSource
代理错误。因此,我没有考虑使用 AOP 方法,而是使用
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 创建错误。

创建带有名称的 bean 时出错 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': 通过构造函数参数0表达的不满足的依赖关系; 嵌套异常是 org.springframework.beans.factory.BeanCreationException:错误 创建类路径资源中定义的名为“dataSource”的 bean [org/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.class]: bean 初始化失败;嵌套异常是 org.springframework.aop.framework.AopConfigException:无法 生成类的CGLIB子类 org.jboss.as.connector.subsystems.datasources.WildFlyDataSource: 此问题的常见原因包括使用最终类或 不可见类;嵌套异常是 org.springframework.cglib.core.CodeGenerationException: java.lang.NoClassDefFoundError-->org/jboss/as/connector/subsystems/datasources/WildFlyDataSource

我还在初始化期间添加了 proxyTargetClass 标志

@EnableAspectJAutoProxy(proxyTargetClass = true)

spring-boot aop jndi spring-aop
2个回答
0
投票

感谢@M.Deinum 建议使用

BeanPostProcessor
并实施
DelegatingDatasource
来设置客户信息。请在下面找到我在 Spring Boot 中实现的实现this的代码片段,它与基于 JBoos JNDI 的连接或 Spring Boot URL 数据源连接配合得很好。

@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
来处理每个用户请求以在数据库连接会话中设置客户端上下文

 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();
    }

}

希望这对面临同样问题的人有帮助


-1
投票

@Karthikeyan 我有类似的用例,我使用 DelegatingDataSource 来拦截连接对象,以便我可以为其设置一些属性。但是,当我在生产中运行此代码时,会创建新的连接对象,并且它们永远不会终止/关闭。我有你上面提到的确切代码。想知道这是否是由于 new (MyDelegateDS) 每次调用时都会创建新连接? PS感谢您分享上面的片段

© www.soinside.com 2019 - 2024. All rights reserved.