Pregunta

Cuando comienzas a jugar con las cosas de proxy automático de Spring, a menudo te encuentras con este comportamiento como se documenta:

  

Clases que implementan el   Interfaz BeanPostProcessor son   especial, y por eso son tratados   diferente por el contenedor. Todos   BeanPostProcessors y sus directamente   los granos referenciados serán instanciados   en el inicio, como parte de la especial   fase de inicio de la   ApplicationContext, entonces todos esos   BeanPostProcessors serán registrados   ordenado - y aplicado a   todos los frijoles más. Desde AOP   el auto-proxy se implementa como   BeanPostProcessor en sí, no   BeanPostProcessors o directamente   los frijoles referenciados son elegibles para   auto-proxy (y por lo tanto no tendrá   aspectos 'entrelazados' en ellos.

     

Para cualquiera de esos frijoles, debería ver un   Mensaje de registro de información: & # 8220; Bean 'foo' no es   elegible para ser procesado por todos   BeanPostProcessors (por ejemplo: no   elegible para auto-proxy) & # 8221 ;.

En otras palabras, si escribo mi propio BeanPostProcessor, y esa clase hace referencia directamente a otros beans en el contexto, entonces esos beans referenciados no serán elegibles para el procesamiento automático, y se registra un mensaje a tal efecto.

Mi problema es que rastrear dónde está esa referencia directa puede ser muy difícil, ya que la "referencia directa" de hecho, puede ser una cadena de dependencias transitivas que termina tomando la mitad de los beans en el contexto de la aplicación. Todo lo que Spring le da es ese único mensaje de información, y en realidad no es de mucha ayuda, además de decirle cuándo un bean ha sido capturado en esta web de referencias.

El BeanPostProcessor que estoy desarrollando tiene referencias directas a otros beans, pero es un conjunto muy limitado de referencias. A pesar de esto, casi todos los beans en mi contexto se excluyen de la representación automática, según los mensajes de registro, pero no puedo ver dónde está sucediendo esa dependencia.

¿Alguien ha encontrado una mejor manera de rastrear esto?

¿Fue útil?

Solución 2

Solo para cerrar un poco esta pregunta, el colapso del gráfico de objeto no inicializado fue causado por el BeanPostProcessor usando @Autowired para obtener sus dependencias y el mecanismo de autoconexión efectivamente causó que cualquier otra definición de bean se inicializara antes de que mi BeanPostProcessor tuviera la oportunidad de opinar sobre el asunto. La solución es no utilizar el cableado automático para sus BPP.

Otros consejos

Sigue esta receta:

  1. Abra BeanPostProcessorChecker en su IDE (es una clase interna de AbstractApplicationContext )
  2. Establezca un punto de interrupción en si (logger.isInfoEnabled ()) { en el método postProcessAfterInitialization
  3. Ejecute su código
  4. Cuando llegues al punto de interrupción, busca las llamadas a getBean (String, Class < T >) en el seguimiento de tu pila.

    Una de estas llamadas intentará crear un BeanPostProcessor . Ese frijol debería ser el culpable.

Trasfondo

Imagina esta situación:

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

Cuando Spring tiene que crear config (ya que es una dependencia de FooPP ), tiene un problema: el contrato dice que todos los BeanPostProcessor debe aplicarse a cada bean que se está creando. Pero cuando Spring necesita config , ¡hay al menos un PP (es decir, FooPP ) que no está listo para el servicio!

Esto empeora cuando usa una clase @Configuration para definir este bean:

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

Cada clase de configuración es un bean. Eso significa construir una fábrica de frijoles a partir de BadSpringConfig , Spring necesita aplicar el fooPP postprocesador, pero para hacer eso, primero necesita la fábrica de frijoles ...

En este ejemplo, es posible romper una de las dependencias cíclicas. Puede hacer que FooPP implemente BeanFactoryAware para que Spring inyecte el BeanFactory en el postprocesador. De esa manera, no necesita cableado automático.

Más adelante en el código, puede pedir perezosamente el 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(...);
}

( fuente de LazyInit )

Para romper el ciclo entre la fábrica de frijoles y el postprocesador, debe configurar el postprocesador en un archivo de configuración XML. Spring puede leer eso y construir todas las estructuras sin confundirse.

No estoy seguro de si es de alguna ayuda, pero los Spring IDE de Eclipse vista gráfica parece que podría ser útil para ordenar las referencias de frijol ..

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top