The scope of a stateless bean is a singleton instance. If we inject Bean B of prototype into Bean A of singleton and hope that a new Bean B can be returned every time the getBeanB() of Bean A is called, this requirement cannot be achieved using traditional injection methods. Because the action of singleton's bean injection of associated beans only occurs once, although the scope of Bean B is prototype type, the object returned through getBeanB() is still the bean B that was injected at the beginning.
So if you want to return a new BeanB every time you call BeanA's getBeanB(), an optional solution is to let BeanA implement the BeanFactoryAware interface, so that you can access the container, and then implement it in the following way.
First configure XML:
<bean id="author" scope="prototype"/><bean id="book" p:name="veil"></bean>
bean author's scope is set to prototype.
The Book class implements the BeanFactoryAware interface:
public class Book implements BeanFactoryAware { ...@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.factory = beanFactory;}public Author getPrototypeAuthor() { return (Author) factory.getBean("author"); }}Unit Tests:
ApplicationContext context;@BeforeMethodpublic void setUp() throws Exception { context = new ClassPathXmlApplicationContext("beans5-5.xml");}@Testpublic void test(){ Book book= (Book) context.getBean("book"); System.out.println(book.getAuthor().hashCode()); System.out.println(book.getAuthor().hashCode()); System.out.println(book.getPrototypeAuthor().hashCode()); System.out.println(book.getPrototypeAuthor().hashCode());Test results
From the results, we can see that only the Author instances obtained from BeanFactory are different.
This implementation binds the application with the Spring framework. Is there a better solution? Yes, it is the injection method.
1 Injection method
Spring containers rely on CGLib libraries, so Class's bytecode can be operated dynamically during runtime, such as dynamically creating subclasses or implementation classes of Beans.
BookInterface interface:
public interface BookInterface { Author getAuthor();}XML configuration:
<!-- Method Injection--><bean id="author" scope="prototype" p:name="Maugham" /><bean id="book2"> <lookup-method name="getAuthor" bean="author"/></bean>
Unit Tests:
BookInterface book= (BookInterface) context.getBean("book2");Assert.assertEquals("Maugham",book.getAuthor().getName());Assert.assertTrue(book.getAuthor().hashCode()!=book.getAuthor().hashCode());Through this configuration method, dynamic implementation can be provided for the interface, and the beans returned in this way are all new instances.
Therefore, if you want to get a prototype bean in a singleton bean, you can use lookup to implement the injection method.
2 Replacement method
In Spring, you can use a method of a certain bean to replace another method of a bean.
Suppose there is a getName() method in Book to get the title:
/** * Book title*/private String name;public String getName() { return name;}We now create a new bean, which implements the MethodReplacer interface to replace the getName() method in the Book:
public class Book4 implements MethodReplacer { @Override public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { return "Alive"; }}Configuration:
<bean id="book3" p:name="Bright Thousand Suns"> <replaced-method name="getName" replacer="book4"/></bean><bean id="book4"/>
test:
Book book= (Book) context.getBean("book3");assertEquals("Living", book.getName()); Summarize
The above is the implementation of the injection or replacement method in the Spring framework introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message. The editor will reply to everyone in time!