huangxfchn edited a comment on issue #15086:
URL:
https://github.com/apache/shardingsphere/issues/15086#issuecomment-1066283999
> @terrymanu Hi~,Brother Liang. My project also uses open-tracing for jdbc,
it will proxy the **getConnection()** method of **javax.sql.DataSource**, and
spring 2.x uses cglib proxy by default, but ShardingSphereDataSource is a final
class. So, if the **ShardingSphereDataSource** is proxied, this exception will
occur. The similar code like this:
>
> ```
> @Aspect
> public class JdbcAspect {
>
> @Around("execution(java.sql.Connection *.getConnection(..)) &&
target(javax.sql.DataSource)")
> public Object getConnection(final ProceedingJoinPoint pjp) throws
Throwable {
> return new TracingConnection(conn);
> }
>
> }
> ```
You can change the proxy of spring to `jdk` proxy, but it is not
recommended. After all, there is a reason why spring boot uses cglib proxy by
default. You can refer to the relevant information
In fact, the best way is to disable dynamic proxying for
`ShardingSphereDataSource`. We can change the beanName of
ShardingSphereDataSource to `shardingSphereDataSource.ORIGINAL` and mark it as
the original instance, so that Spring AOP will not proxy
`ShardingSphereDataSource`. The relevant code of Spring AOP is as follows:
```
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
AutoProxyUtils#isOriginalInstance
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
if (!StringUtils.hasLength(beanName) || beanName.length() !=
beanClass.getName().length() +
AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
return false;
}
return (beanName.startsWith(beanClass.getName()) &&
beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
}
```
1. **Option 1, declare the `DataSource` defined in
`ShardingSphereAutoConfiguration.java` as
`@Bean("shardingSphereDataSource.ORIGINAL")`, `@Bean("dataSource.ORIGINAL")`**
```
public class ShardingSphereAutoConfiguration implements EnvironmentAware {
@Bean("shardingSphereDataSource.ORIGINAL")
@Conditional(LocalRulesCondition.class)
@Autowired(required = false)
public DataSource shardingSphereDataSource(final
ObjectProvider<List<RuleConfiguration>> rules, final
ObjectProvider<ModeConfiguration> modeConfig) throws SQLException {
//……
}
@Bean("dataSource.ORIGINAL")
@ConditionalOnMissingBean(DataSource.class)
public DataSource dataSource(final ModeConfiguration modeConfig) throws
SQLException {
return ShardingSphereDataSourceFactory.createDataSource(schemaName,
modeConfig);
}
}
```
3. **Option 2, modify `beanName` through
`BeanDefinitionRegistryPostProcessor`**, the code is as follows:
```
@Configuration
public class ShardingSphereRegistryPostProcessor implements
BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry
registry) throws BeansException {
String className = ShardingSphereDataSource.class.getName();
String beanName = "shardingSphereDataSource";
if(registry.containsBeanDefinition(beanName)){
BeanDefinition shardingSphereDataSource =
registry.getBeanDefinition(beanName);
registry.removeBeanDefinition(beanName);
registry.registerBeanDefinition(className +
AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX , shardingSphereDataSource);
return;
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory
beanFactory) throws BeansException {
}
}
```
Personally, I prefer the official modification of beanName by shardingSphere.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]