[Spring] Spring method injection non-singleton bean call

Source: Internet
Author: User

Http://flysnow.iteye.com/blog/733785 #

In most cases, the bean in the container is of the singleton type. If a singleton bean references another Singleton bean, or a non-singleton bean references another non-singleton bean, generally, you can define a bean as the property value of another bean. However, this will be problematic for beans with different lifecycles. For example, when calling a method of a singleton bean A, you need to reference another non-singleton (prototype) bean B of the type. For bean A, the container is only created once, so that the container cannot provide a new bean B instance for bean a every time when necessary.

Spring provides three solutions for the above problems:

  • Discard control inversion. Implement the applicationcontextaware interface to enable bean a to perceive Bean
    Container, and use getbean ("B") to request a new bean B instance from the container as needed.
  • Lookup method injection. Lookup method injection uses the container's ability to overwrite the bean method managed by the container, and returns the bean instance with the specified name.
  • An alternative to a custom method. This injection can use another bean method to replace the custom method.

Here, we only talk about the implementation of the first two solutions. The third solution is not commonly used and is omitted. If you are interested, please take a look.

I. Implementation Environment

  • Eclipse3.4
  • Jdk1.5
  • Spring3.0.3
  • JUnit 4 testing framework
  • Dependent jar has log4j-1.2.16.jar, commons-logging-api-1.1.1.jar, cglib-nodep-2.2.jar.

2. Implement the applicationcontextaware interface programmatically
Applicationcontextaware and beanfactoryaware are similar in usage.
The object of the applicationcontextaware interface will have an applicationcontext reference, so that we can operate it programmatically.
Applicationcontext. Let's look at the example below.

1 package COM. flysnow. injection; 2 3 Import Org. springframework. beans. beansexception; 4 Import Org. springframework. context. applicationcontext; 5 import Org. springframework. context. applicationcontextaware; 6 7 Import COM. flysnow. injection. command. command; 8 9/** 10 * command manager 11 * @ author feixue heartless 12*13 */14 public class commandmanager implements applicationcontextaware {15 // used to save the reference of applicationcontext, 16 private applicationcontext injection in set mode; 17 // method of simulating business processing 18 public object process () {19 command = createcommand (); 20 return command.exe cute (); 21} 22 // get a command 23 private command createcommand () {24 return (command) This. applicationcontext. getbean ("asynccommand"); // 25} 26 27 public void setapplicationcontext (applicationcontext) 28 throws beansexception {29 This. applicationcontext = applicationcontext; // obtain the applicationcontext reference 30} 31 32}

The following defines the command interface and its implementation class asynccommand.

1 package COM. flysnow. injection. command; 2 3/** 4 * a command interface 5 * @ author feixue heartless 6*7 */8 public interface command {9/** 10 * Execute Command 11 * @ return12 */ 13 public object execute (); 14}
1 package COM. flysnow. injection. command; 2 3/** 4 * Implementation of an asynchronous Processing Command 5 * @ author feixue heartless 6*7 */8 public class asynccommand implements command {9 10/* (non-javadoc) 11 * @ see COM. flysnow. lookup. command. command # execute () 12 */13 public object execute () {14 // return its own instance, so that during the test, we can see that each return is not the same instance 15 return this; 16} 17 18}

The bean configuration file is as follows:

<? XML version = "1.0" encoding = "UTF-8"?> <Beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <! -- Use scope = "prototype" to define the bean as multi-sample --> <bean id = "asynccommand" class = "com. flysnow. injection. command. asynccommand "Scope =" prototype "> </bean> <bean id =" commandmanager "class =" com. flysnow. injection. commandmanager "> </bean> </beans>

The process () method of the single-instance bean commandmanager must reference a prototype (not single-instance) bean, therefore, when calling process, you first obtain a command from the container through the createcommand method, and then execute business computing. The Code contains comments, which is very simple.
The test class is as follows:

Package COM. flysnow. injection; import Org. JUnit. before; import Org. JUnit. test; import Org. springframework. context. applicationcontext; import Org. springframework. context. support. classpathxmlapplicationcontext; import COM. flysnow. injection. commandmanager; public class testcommandmanager {private applicationcontext context; @ before public void setup () throws exception {context = new classpathxmlapplicationcontext ("beans. XML ") ;}@ test public void testprocess () {commandmanager manager = context. getbean ("commandmanager", commandmanager. class); system. out. println ("the first execution process, command address is:" + manager. process (); system. out. println ("the second execution process, command address is:" + manager. process ());}}

The command address in the output borrow is different from the command address in the console, because the scope = "prototype" attribute is configured for asynccommand, this method makes the bean instances obtained from the container different each time. In this way, we implement the process method in the commandmanager (single-instance bean) to reference the bean (asynccommand) that is not single-instance ). Although we have implemented it, this is not a good method because our business code is coupled with Spring framework. Next we will introduce another clean implementation method provided by spring, namely lookup method injection.

Iii. Implemented through lookup method Injection

This method is very simple, because Spring has done a lot of work for us, and we need to do bean configuration and business class.

  • First, modify the commandmanager class to abstract, and modify the createcommand method to abstract.
  • Remove the implementation of applicationcontextaware and the related set method and applicationcontext variable definition.
  • Modify the bean configuration file and add <lookup-method name = "createcommand" bean = "asynccommand"/> to the commandmanager bean.
  • Others remain unchanged

The modified commandmanager and bean configuration files are as follows:

1 public abstract class commandmanager {2 // method for simulating business processing 3 Public object process () {4 command = createcommand (); 5 return command.exe cute (); 6} 7 // get a command 8 protected abstract command createcommand (); 9}

 

<bean id="commandManager" class="com.flysnow.injection.CommandManager">            <lookup-method name="createCommand" bean="asyncCommand"/>        </bean>

Run the test. The addresses of the two commands printed on the console are different.
<Lookup-method> the name attribute in the tag is commandmanager.
The method for obtaining the command instance (asynccommand) of bean, that is, the createcommand method. Which type of bean attribute is returned?
Command. Here is asynccommand.

The createcommand method becomes the injection method, and its definition form must be:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

The injected method is not necessarily abstract. If the injected method is abstract, the dynamically generated subclass (The subclass of the dynamically generated commandmanager) will implement this method. Otherwise, the dynamically generated subclass will overwrite the specific methods in the class. To make this dynamic subclass work properly, you need to put the cglib JAR file in classpath, which is why we reference the cglib package. Also, the commandmanager class to be subclass by spring containers cannot be final, and the createcommand method to be overwritten cannot be final.

Iv. Summary

The lookup method is clean and tidy, easy to expand, and more in line with IOC rules, so try to use this method.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.