what the mvc life for business beans bean applicationcontextaware annotation spring

the - Spring Prototype midió el frijol en un singleton



what is the role of applicationcontextaware in spring? (4)

Intento inyectar un prototipo de frijol en un bean singleton de modo que cada nueva llamada a un método de bean singleton tenga una nueva instancia del bean prototipo.

Considere un frijol singleton como a continuación:

@Component public class SingletonBean{ @Autowired private PrototypeBean prototypeBean; public void doSomething(){ prototypeBean.setX(1); prototypeBean.display(); } }

Espero que cada vez que se llame al método doSomething (), se utilice una nueva instancia de PrototypeBean.

Debajo está el prototipo de frijol:

@Component @Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) public class PrototypeBean{ Integer x; void setX(Integer x){ this.x = x; } void display(){ System.out.println(x); } }

Lo que parece estar sucediendo es que la primavera está deseando entregar una nueva instancia de PrototypeBean en el método doSomething (). Es decir, las 2 líneas de código en el método doSomething () están creando una nueva instancia de prototypeBean en cada línea. Y así en la 2da línea - prototypeBean.display () imprime NULL.

¿Es este el comportamiento esperado o me perdí alguna configuración para inyectar el prototipo de frijol correctamente?


De la documentation Spring:

No necesita usar el <aop:scoped-proxy/> junto con los beans que tienen un ámbito como singleton o prototipos. Si intenta crear un proxy con ámbito para un bean Singleton, se genera la BeanCreationException.

Parece que la documentación ha cambiado un poco para la documentation de la versión 3.2 donde puedes encontrar esta oración:

No necesita usar el <aop:scoped-proxy/> junto con los beans que tienen un ámbito como singleton o prototipos.

Parece que no se espera que utilice un prototipo de bean BeanFactory , ya que cada vez que se solicita al BeanFactory creará una nueva instancia de este.

Para tener un tipo de fábrica para su prototipo de frijol, puede usar un ObjectFactory siguiente manera:

@Component public class SingletonBean { @Autowired private ObjectFactory<PrototypeBean> prototypeFactory; public void doSomething() { PrototypeBean prototypeBean = prototypeFactory.getObject(); prototypeBean.setX(1); prototypeBean.display(); } }

y su prototipo de frijol se declararía de la siguiente manera:

@Component @Scope(value="prototype") public class PrototypeBean { // ... }


El bean Singleton se crea solo una vez, por lo que el bean prototipo que se inyecta también se creará una vez en la instanciación del bean singleton. Se usará la misma instancia de bean prototipo para cada solicitud.

Si se creará una nueva instancia de prototipo de bean para cada solicitud en tiempo de ejecución, se puede usar la inyección de método siguiente.

Ejemplo

public class Singleton { private Prototype prototype; public Singleton(Prototype prototype) { this.prototype = prototype; } public void doSomething() { prototype.foo(); } public void doSomethingElse() { prototype.bar(); } } public abstract class Singleton { protected abstract Prototype createPrototype(); public void doSomething() { createPrototype().foo(); } public void doSomethingElse() { createPrototype().bar(); } } <bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" /> <bean id="singleton" class="sample.MySingleton"> <lookup-method name="createPrototype" bean="prototype" /> </bean>


El resorte conecta tus granos de manera bastante directa. Estoy trabajando en una gran aplicación comercial e inserté los siguientes fragmentos de código para verificar el orden de carga.

1) Todas las estructuras de clase de bean singleton son cargadas inicialmente por Spring (siempre que Spring las conozca mediante anotaciones y / o xml). Esto solo sucede una vez. Puede probar esto al iniciar sesión o imprimir en un bloque estático:

static { log.info("#### classNameHere loaded"); //or println if no log setup }

2) Spring crea todas las instancias singleton de las que tiene constancia (¡pero no prototipos!) Se crearán instancias de prototipos SI se referencian dentro de un bean singleton, por supuesto, las estructuras de clase se cargan primero). Puede probar esto agregando este método a cada clase:

@PostConstruct public void methodHitAfterClassInstantiation() { LOGGER.info("#### instance of classNameHere"); }

Entonces, en su ejemplo, las estructuras de clase de SingletonBean se cargan cuando se inicia Spring. Se crea una nueva instancia de SingletonBean. Y debido a que PrototypeBean está Autowired dentro de SingletonBean, su estructura de clase se carga y se crea una instancia de la misma. Ahora, si hubiera otro bean, digamos AnotherSingletonBean, con un Autowired PrototypeBean dentro de él, entonces se crearía una instancia DIFERENTE de PrototypeBean (no es necesario cargar la estructura de clases nuevamente). Entonces, solo hay 1 SingletonBean, y dentro de él, un PrototypeBean, que siempre apunta al mismo bean. Debido a esto, los singletons siempre deben ser apátridas, ya que todos los demás beans que usan singleton apuntan al mismo objeto. Pero PUEDE mantener el estado en un prototipo de frijol, porque donde quiera que cree una nueva referencia, estará apuntando a otro objeto de frijol. http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype


La manera correcta de lograrlo: use la inyección del método de búsqueda y en todas partes donde usó los beans utilice la invocación del método de búsqueda ( respuesta detallada )