Pergunta

Quando você começa a mexer com coisas auto-proxy da Primavera, muitas vezes você correr para esse comportamento como documentadas:

classes que implementam a Interface BeanPostProcessor são especial, e assim eles são tratados de modo diferente pelo recipiente. Tudo BeanPostProcessors e sua diretamente feijão referenciados será instanciado no arranque, como parte do especial fase de arranque do ApplicationContext, então todos aqueles BeanPostProcessors será registrado de uma forma ordenada - e aplicada a todos os outros feijões. desde AOP auto-proxy é implementado como um BeanPostProcessor em si, não BeanPostProcessors ou directamente feijão referenciados são elegíveis para auto-proxy (e, portanto, não terá aspectos 'tecido' para eles.

Para qualquer um desses feijão, você deve ver uma Informações mensagem de log: “Feijão 'foo' não é elegíveis para se processada por todos BeanPostProcessors (por exemplo: não elegíveis para auto-proxy)”.

Em outras palavras, se eu escrever meu próprio BeanPostProcessor, e essa classe diretamente referências outros feijões no contexto, então esses grãos de referência não serão elegíveis para auto-proxy, e uma mensagem é registrada para esse efeito.

Meu problema é que rastrear onde essa referência direta é pode ser muito difícil, uma vez que a lata "referência direta" no fato de ser uma cadeia de dependências transitivas que acaba levando na metade do feijão no contexto da aplicação. Todos Primavera dá-lhe é que única informação mensagem, e não é realmente muita ajuda, para além dizendo que quando um feijão foi preso nesta teia de referências.

O BeanPostProcessor Estou desenvolvendo tem referências diretas a outros feijões, mas é um conjunto muito limitado de referências. Apesar disso, praticamente todos os feijão no meu contexto é então a ser excluído da qualidade proxy automaticamente, de acordo com as mensagens de log, mas eu não consigo ver onde essa dependência está acontecendo.

Alguém encontrou uma maneira melhor de acompanhar este baixo?

Foi útil?

Solução 2

Apenas para trazer algum fechamento a esta pergunta, o colapso do gráfico de objeto não inicializado foi causado pela BeanPostProcessor usando @Autowired para obter suas dependências, eo mecanismo autowire efetivamente causado qualquer outra definição de feijão para ser inicializado antes do meu BeanPostProcessor tem uma chance ter uma palavra a dizer na matéria. A solução não é para uso autowiring para seus BPPs.

Outras dicas

Siga esta receita:

  1. Open BeanPostProcessorChecker em sua IDE (é uma classe interna de AbstractApplicationContext)
  2. Definir um ponto de interrupção if (logger.isInfoEnabled()) { na postProcessAfterInitialization método
  3. Execute o código
  4. Quando você atinge o ponto de interrupção, olhar para chamadas para getBean(String,Class<T>) em seu rastreamento de pilha.

    Uma dessas chamadas vão tentar criar um BeanPostProcessor. Isso feijão deve ser o culpado.

Fundo

Imagine esta situação:

public class FooPP implements BeanPostProcessor {
    @Autowire
    private Config config;
}

Quando a mola tem que criar config (já que é uma dependência de FooPP), tem um problema: O contrato diz que todos BeanPostProcessor deve ser aplicada a cada grão que está sendo criado. Mas quando Primavera precisa config, há pelo menos uma PP (nomeadamente FooPP), que não está pronto para o serviço!

Este fica pior quando você usa uma classe @Configuration para definir esse bean:

@Configuration
public class BadSpringConfig {
     @Lazy @Bean public Config config() { return new Config(); }
     @Lazy @Bean public FooPP fooPP() { return new FooPP(); }
}

Cada classe de configuração é um bean. Isso significa que para construir uma fábrica de feijão de BadSpringConfig, Primavera precisa aplicar o fooPP pós-processador, mas para fazer isso, ele primeiro precisa a fábrica de feijão ...

Neste exemplo, é possível quebrar uma das dependências cíclicas. Você pode fazer FooPP implementar BeanFactoryAware para obter Primavera injetar o BeanFactory no processador post. Dessa forma, você não precisa autowiring.

Mais tarde no código, você pode preguiçosamente pedir o bean:

private LazyInit<Config> helper = new LazyInit<Config>() {

    @Override
    protected InjectionHelper computeValue() {
        return beanFactory.getBean( Config.class );
    }
};

@Override
public Object postProcessBeforeInitialization( Object bean, String beanName ) throws BeansException {
     String value = helper.get().getConfig(...);
}

( para LazyInit )

Para quebrar o ciclo entre a fábrica de feijão eo pós-processador, você precisa configurar o pós-processador em um arquivo de configuração XML. Primavera pode ler isso e construir todas as estruturas sem se confundirem.

Não tenho certeza se é de alguma ajuda, mas o Eclipse Primavera IDE 's gráfico visualizar olhares como ele poderia ser útil em resolver referências de feijão ..

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top