【发布时间】:2021-09-13 10:28:00
【问题描述】:
我正在尝试为我的数据源创建一个代理来监督数据库查询,但是从未使用 bean 数据源对象调用以下内容,并且 bean instanceof DataSource 始终为 false:
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Clock;
import java.util.List;
import javax.sql.DataSource;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.metrics.MetricsEndpoint;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.talan.dbmonitor.config.RabbitMQProperties;
import com.talan.dbmonitor.listeners.QueryListener;
import com.talan.dbmonitor.service.MapperService;
import lombok.extern.slf4j.Slf4j;
import net.ttddyy.dsproxy.support.ProxyDataSource;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
@Configuration
@ConditionalOnProperty(value="enable.dbmonitor", havingValue="true", matchIfMissing= false)
@Slf4j
public class DatasourceProxyBeanPostProcessor implements BeanPostProcessor {
@Autowired
private AmqpTemplate amqpTemplate;
@Autowired
private Clock clock;
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Autowired
private MetricsEndpoint metricsendpoint;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private MapperService mapperService;
@Value("#{T(java.util.Arrays).asList('${dbmonitor.tables.ignore.list:}')}")
List<String> tablesIgnoreList;
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) {
return bean;
}
@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) {
System.out.println(beanName+" : "+bean.getClass().toString());
System.out.println((bean instanceof DataSource));
if (bean instanceof DataSource && !(bean instanceof ProxyDataSource)) {
ProxyFactory factory = new ProxyFactory(bean);
factory.setProxyTargetClass(true);
factory.addAdvice(new ProxyDataSourceInterceptor((DataSource) bean, amqpTemplate,
rabbitMQProperties, metricsendpoint, objectMapper, mapperService, tablesIgnoreList ,clock
));
return factory.getProxy() == null ? factory.getProxy() : bean;
}
return bean;
}
private static class ProxyDataSourceInterceptor implements MethodInterceptor {
private final DataSource dataSource;
public ProxyDataSourceInterceptor(final DataSource dataSource, AmqpTemplate amqpTemplate,
RabbitMQProperties rabbitMQProperties,MetricsEndpoint metricsendpoint,ObjectMapper objectMapper,MapperService mapperService,
List<String> tablesIgnoreList ,Clock clock
) {
super();
QueryListener qListener = new QueryListener(amqpTemplate, rabbitMQProperties,metricsendpoint,objectMapper, mapperService, tablesIgnoreList , clock
);
String datasourceUrl = null;
try (Connection datasourceConnection = dataSource.getConnection()){
datasourceUrl = datasourceConnection.getMetaData().getURL();
} catch (SQLException e) {
log.warn(e.getMessage());
}
finally {
this.dataSource = ProxyDataSourceBuilder.create(dataSource).name(datasourceUrl).countQuery()
.listener(qListener).build();
}
}
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
Method proxyMethod = ReflectionUtils.findMethod(dataSource.getClass(), invocation.getMethod().getName());
if (proxyMethod != null) {
return proxyMethod.invoke(dataSource, invocation.getArguments());
}
return invocation.proceed();
}
}
}
数据源设置:
spring.datasource.platform = postgres
spring.datasource.url= jdbc:postgresql://${DB_SERVER_HOST:localhost}:${DB_SERVER_PORT:5432}/${DB_NAME:polaris_db}
spring.datasource.username= ${DB_USER:postgres}
spring.datasource.password= ${DB_PASSWORD:yosra}
spring.datasource.driverClassName= org.postgresql.Driver
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQLDialect
Spring boot 版本:2.3.7.RELEASE
问题是 postProcessAfterInitialization 中的这条指令永远不会被验证,所以我的代理永远不会被调用
bean instanceof DataSource && !(bean instanceof ProxyDataSource)
【问题讨论】:
标签: java spring-boot hibernate proxy spring-data-jpa