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 java
framework 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.
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 ComplexKeysShardingAlgorithm
dessa 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:
Como essa classe é
Null
fragmentaçã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 info
log
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 BeanPostProcessor
processado (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 beanpostProcessor
nã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:
从流程中可以看见
BeanPostProcessor
的注册是在applicationcentest生命周期内完成的,故而当bean
创建时,如果相应拦截器还没有注册,那么其就不会起作用。所以sharding-jdbc实现的自定义分片算法里面的init()
方法不生效可能就是如下原因:
- bean由于某种原因,被提前初始化了,但是相应的拦截器
BeanPostProcessor
还没有注册,所以不执行方法
BeanPostProcessor接口作用:
简单来讲,就是在实例化bean、配合bean以及其他初始化方法前后想增加一些自己的逻辑处理,就可以继承这个接口进行
在doGet()方法中debug查看被谁提前加载了
找到 AbstractBeanFactory这个对象下面的doGet()方法并且设置条件断点test-algorithm
看看是哪个小哪吒提前加载导致这个bean不生效了
定位到断点,并且向上查找看看哪个bean提前注册了
最终找到[1]里面的
shiroFilter
方法导致shardingBean被提前注册了
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容器
Então pesquisamos ao longo do acima, e finalmente encontramos o seguinte método: foi
encontrado
AuthorizingRealm
que o objeto que o herdou foi introduzido, UserService
então não foi fácil de usar.
solução
plano 1
EnceladusShiroRealm
Obtenha 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.setFilterChainDefinitionMap
novos 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();
}
}
ShiroFilterFactoryBean
Encapsular , descartar métodos relacionados, encapsular beans como beans comuns do Spring e fazer downgradeBeanPostProcessor
de ShiroFilterFactoryBean
- Usando wrapper beans para registro de retorno no Spring
A habilitação init()
do método de descoberta de projeto novamente está concluída.
Até 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.