O algoritmo de fragmentação personalizado do sharding-jdbc entra em conflito com o shrio e não entra em vigor

fundo

Devido à expansão dos negócios da empresa, a quantidade de dados continua crescendo, fazendo com que a velocidade de retorno das consultas seja muito lenta, por isso precisa ser otimizada. Após a investigação, vamos usar a tecnologia de sub-tabela de banco de dados para resolver o problema de velocidade de consulta lenta.

Tecnologia de fragmentação de tabela-Fragmentação-JDBC

É um javaframework leve e uma versão aprimorada do driver JDBC, que simplifica a dificuldade das operações de dados após sub-banco de dados e sub-tabela, de forma que os usuários só precisam prestar atenção ao negócio.

imagem.png

Descrição do Problema

Devido à particularidade do negócio, o algoritmo de fragmentação fornecido pelo sharding-jdbc não é muito adequado para nossos requisitos de fragmentação de tabela, portanto, o algoritmo de fragmentação personalizado fornecido é usado para fragmentação. sharding-jdbc requer a implementação ComplexKeysShardingAlgorithmdessa interface para reescrever o algoritmo de fragmentação, mas após a implementação, verifica-se que o algoritmo de fragmentação não entra em vigor e a classe de implementação personalizada não é carregada, o que a torna inutilizável. O log do console é o seguinte:

imagem.pngComo essa classe é Nullfragmentação, ela não pode encontrar o método correspondente para carregar ao pesquisar o algoritmo de fragmentação.

método init não executado

O método ClassBasedShardingAlgorithm.init() não é executado, resultando em um objeto complexKeysShardingAlgorithm vazio

Este método será carregado quando o programa spring for iniciado, mas na inicialização este método não é executado, mas o contêiner de bean também foi criado após a inicialização.

Ver registro do console

Ao visualizar o log do console, verifica-se que o log imprime o seguinte infolog

14:35:01.505 [main] INFO  o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - [postProcessAfterInitialization,330] - Bean 'test-algorithm' of type [org.apache.shardingsphere.sharding.algorithm.sharding.classbased.ClassBasedShardingAlgorithm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

Significa presumivelmente não atender às condições para ser BeanPostProcessorprocessado (por exemplo: não atender às condições para agentes automáticos)

Ou seja, o bean é inicializado antecipadamente por algum motivo e o interceptor correspondente beanpostProcessornão foi registrado no momento da inicialização, portanto, o método de processamento correspondente não é executado.

Envolve a série de código fonte da mola e o ciclo de carregamento do bean.

ciclo de vida do feijão

Ilustração do processo de instanciação de beans na primavera:

imagem.png 从流程中可以看见BeanPostProcessor的注册是在applicationcentest生命周期内完成的,故而当bean创建时,如果相应拦截器还没有注册,那么其就不会起作用。所以sharding-jdbc实现的自定义分片算法里面的init()方法不生效可能就是如下原因:

  • bean由于某种原因,被提前初始化了,但是相应的拦截器BeanPostProcessor还没有注册,所以不执行方法

BeanPostProcessor接口作用:

简单来讲,就是在实例化bean、配合bean以及其他初始化方法前后想增加一些自己的逻辑处理,就可以继承这个接口进行

在doGet()方法中debug查看被谁提前加载了

找到 AbstractBeanFactory这个对象下面的doGet()方法并且设置条件断点test-algorithm看看是哪个小哪吒提前加载导致这个bean不生效了

imagem.png 定位到断点,并且向上查找看看哪个bean提前注册了

imagem.png 最终找到[1]里面的shiroFilter方法导致shardingBean被提前注册了

imagem.png test-algorithm执行顺序如下

test-algorithm
    org.apache.shardingsphere.sharding.spring.boot.ShardingRuleSpringBootConfiguration
         org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
             com.sinowel.assistant.assistantsystem.service.impl.UserServiceImpl
                 com.sinowel.assistant.assistantsystem.service.UserService
                     com.sinowel.assistant.assistantsystem.config.ShiroConfig
                     

这样bean的加载就清晰明了,也就是说因为shiroConfig里面的某个配置导致被提前加载。我们在往上找,发现ShiroRealm这个bean,那从debug分析,也就是说,在shiroRealm这个实现类里,注入了UserService这个对象,所以导致实现的shrding-jdbc的BeanPostProcessor被加载.

在shirFilter中有一个ShiroFilterFactoryBean对象,这个对象实际继承了BeanPostProcessor它,所以在初始化的时候就会加载一系列被依赖的Bean容器

imagem.png

imagem.pngEntão pesquisamos ao longo do acima, e finalmente encontramos o seguinte método: foi imagem.pngencontrado AuthorizingRealmque o objeto que o herdou foi introduzido, UserServiceentão não foi fácil de usar.

imagem.png

solução

plano 1

EnceladusShiroRealmObtenha manualmente o método de uso do bean no método springContext.getBean(), para que, quando carregado, esteja bem.

Cenário 2

  • Todos os filtros relacionados ao shiro são ShiroFilterFactoryBean.setFilterChainDefinitionMapnovos no ,
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.FactoryBean;

public class MyShiroFilterFactoryBean implements FactoryBean<AbstractShiroFilter> {
    private final ShiroFilterFactoryBean shiroFilterFactoryBean;

    public MyShiroFilterFactoryBean(ShiroFilterFactoryBean shiroFilterFactoryBean) {
        this.shiroFilterFactoryBean = shiroFilterFactoryBean;
    }

    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
        return shiroFilterFactoryBean;
    }

    @Override
    public AbstractShiroFilter getObject() throws Exception {
        return (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
    }

    @Override
    public Class<?> getObjectType() {
        return shiroFilterFactoryBean.getObjectType();
    }

    @Override
    public boolean isSingleton() {
        return shiroFilterFactoryBean.isSingleton();
    }
}
  • ShiroFilterFactoryBeanEncapsular , descartar métodos relacionados, encapsular beans como beans comuns do Spring e fazer downgradeBeanPostProcessor de ShiroFilterFactoryBean

imagem.png

  • Usando wrapper beans para registro de retorno no Spring

A habilitação init()do método de descoberta de projeto novamente está concluída.

imagem.pngAté agora o problema foi resolvido

Resumir

Após essa localização e pesquisa do problema, você pode ter uma impressão mais profunda do gerenciamento de beans do spring.

おすすめ

転載: juejin.im/post/7120517655181656078