Read the official document together ---- spring IOC (04)

1.4.2. Dependencies and detailed configuration

As described in the previous section, you can define bean properties and constructor parameters as references to other managed beans (collaborators) or inline defined values. Spring's XML based configuration metadata supports child element types in its and elements for this purpose.

Direct value (primitive, string, etc.)
The attribute element described in value specifies a human readable String representation of the attribute or constructor parameter. Spring's transformation service is used to convert these values from String to the actual type of property or parameter. The following example shows the various values set:

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- results in a setDriverClassName(String) call -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="misterkaoli"/>
</bean>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/mydb"
        p:username="root"
        p:password="misterkaoli"/>

</beans>

The previous XML is more concise. However, spelling errors are found at runtime, not at design time, unless you use an IDE (such as IntelliJ IDEA or the Spring tool for Eclipse) to support automatic property completion when creating bean definitions.

You can also configure Java util. The properties instance is as follows:

<bean id="mappings"
    class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="properties">
        <value>
            jdbc.driver.className=com.mysql.jdbc.Driver
            jdbc.url=jdbc:mysql://localhost:3306/mydb
        </value>
    </property>
</bean>

The Spring container converts the text in the element into Java util. Property instance by using JavaBeans' PropertyEditor mechanism. This is a good shortcut and one of several places where the Spring team prefers nested elements to value attribute styles.

idref element

The idref element is an error proofing method, mainly by passing the id of another bean in the container (passing the id as a string value rather than a reference) to the or tag.

The following example shows how to use it:

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        //Here, theTargetBean is passed as a string to the targetName attribute of theClientBean
        //Instead of passing the instance of the targetName bean to the targetName attribute
        <idref bean="theTargetBean"/>
    </property>
</bean>

The preceding bean definition code snippet (at run time) is completely equivalent to the following code snippet:
idref is equivalent to the value tag, not the ref tag

<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
    <property name="targetName" value="theTargetBean"/>
</bean>
Elemental local Attribute in idref4.0 Bean XSD Is no longer supported in because it no longer provides general bean The value on the reference.
Upgrade to 4.0 Mode, the existing idref local Reference changed to idref bean. 

idref usage can verify that the id passed in as a bean will be used to verify whether the bean with the current id exists

<idref></idref>Common locations of elements(At least spring2.0 In previous versions)Yes ProxyFactoryBean bean In definition AOP Interceptor configuration in progress.
Used when specifying the interceptor name<idref></idref>Element prevents spelling errors.
ref to other beans

The ref element is the last element in the or definition element. Here, you set the value of the specified property of the bean to a reference to another bean managed by the container. The referenced bean is a dependency of the bean whose properties are to be set, and it is initialized as needed before setting the properties (if the collaborator is a singleton bean, it may have been initialized by the container). All references are ultimately references to another object. Depending on whether the name or other property of the specified bean has passed validation.

Specifying the target bean through the bean attribute of the tag is the most common form, which allows the creation of a reference to any bean in the same container or parent container, regardless of whether it is in the same XML file or not. The value of the bean attribute can be the same as the id attribute of the target bean, or the same as a value in the name attribute of the target bean. The following example shows how to use the ref element:

//someBean can be the id of the bean or the name of the bean
<ref bean="someBean"/>

The local attribute of ref element is in ref4 0 is no longer supported in bean XSD,
Because it no longer provides values on regular bean references. When upgrading to 4.0 mode, change the existing ref local reference to ref bean.

aggregate

The,,, and elements set the properties and parameters of Java collection types list, set, map, and properties respectively. The following examples show how to use them:

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

The key or value of map or the value of set can also be any of the following elements:

bean | ref | idref | list | set | map | props | value | null
Collection merge

The Spring container also supports merging collections. Application developers can define a parent element,, or, and let child elements,, or inherit and overwrite the values of the parent element set. That is, the value of the subset is the result of merging the elements of the parent set and the subset, and the elements of the subset override the values specified in the parent set.

The section on merging discusses the parent-child bean mechanism. Readers unfamiliar with parent and child bean definitions may wish to read the relevant sections before proceeding.

The following example demonstrates collection merging:

<beans>
    <bean id="parent" abstract="true" class="example.ComplexObject">
        <property name="adminEmails">
            <props>
                <prop key="administrator">administrator@example.com</prop>
                <prop key="support">support@example.com</prop>
            </props>
        </property>
    </bean>
    <bean id="child" parent="parent">
        <property name="adminEmails">
            <!-- the merge is specified on the child collection definition -->
            <props merge="true">
                <prop key="sales">sales@example.com</prop>
                <prop key="support">support@example.co.uk</prop>
            </props>
        </property>
    </bean>
<beans>

Note that the merge=true attribute is used on the element of the adminEmails attribute defined by the sub bean. When the container parses and instantiates the child bean, the generated instance has a collection of adminEmails attributes, which contains the result of merging the adminEmails collection of the child bean with the adminEmails collection of the parent bean. The following listing shows the results:

administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk

The value set of the child attribute set inherits all attribute elements in the parent attribute, and the value of the child attribute support value overrides the value in the parent attribute set.

This merge behavior applies similarly to,, and collection types. In the specific case of an element, the semantics associated with the list collection type (that is, the concept of an ordered Set of values) will be maintained. The value of the parent element precedes the value of the list of all child elements. There is no sort for Map, Set, and Properties collection types. Therefore, sorting semantics do not work for collection types under the association mapping, collection and attribute implementation types used inside the container.

Limitations of collection merging

You cannot merge different collection types (such as Map and List). If you try to do this, an exception will be thrown.
The merge property must be specified in the following inherited subset definition.
Merge specifying attributes on the parent collection definition is redundant and will not result in the required merge.

Strongly typed set

With the introduction of generic types in Java 5, you can use strongly typed collections. That is, you can declare a Collection type that contains only, for example, String elements. If you use Spring to inject strongly typed dependencies into a Collection bean, you can take advantage of Spring's type conversion support to convert the elements of a strongly typed Collection instance to the appropriate type Collection before adding them to the bean. The following Java class and bean definitions show how to do this:

public class SomeClass {
    private Map<String, Float> accounts;
    public void setAccounts(Map<String, Float> accounts) {
        this.accounts = accounts;
    }
}
<beans>
    <bean id="something" class="x.y.SomeClass">
        <property name="accounts">
            <map>
                <entry key="one" value="9.99"/>
                <entry key="two" value="2.75"/>
                <entry key="six" value="3.99"/>
            </map>
        </property>
    </bean>
</beans>

When ready to inject bean of accounts Property,
It can be obtained by reflection something Generic information about strongly typed element types Map<String,Float>. 
So, Spring The type conversion infrastructure of recognizes various value elements as type Float´╝î
And the string value (9.99, 2.75 And 3.99)Convert to actual Float Type.
Empty string value and empty string value

Spring treats empty parameters such as attributes as empty strings. The following xml based configuration metadata fragment sets the email attribute to an empty string value ("").

<bean class="ExampleBean">
    <property name="email" value=""/>
</bean>

The previous example is equivalent to the following Java code:

exampleBean.setEmail("");

This element handles null values. The following listing shows an example:

<bean class="ExampleBean">
    <property name="email">
        <null/>
    </property>
</bean>

The previous configuration is equivalent to the following Java code:

exampleBean.setEmail(null);
XML shortcut with p-namespace

The p-namespace allows you to use the attributes of bean elements (rather than nested elements) to describe the attribute values of the beans with which you cooperate, or both.

Spring supports extensible configuration formats with namespaces, which are defined based on XML schemas. The bean configuration format discussed in this chapter is defined in the XML schema document. However, the p-namespace is not defined in the XSD file and only exists in the core of spring.

The following example shows two XML fragments that parse to the same result (the first using standard XML format and the second using p-namespace):

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework. Org / schema / P "<! -- this line is for -- >
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="classic" class="com.example.ExampleBean">
        <property name="email" value="someone@somewhere.com"/>
    </bean>

    <bean name="p-namespace" class="com.example.ExampleBean"
        p:email="someone@somewhere.com"/>
</beans>

This example shows the properties of email in the p-namespace called in the bean definition. This tells Spring to include a property declaration. As mentioned earlier, the P namespace has no schema definition, so you can set the attribute name to the attribute name.

The next example includes two other bean definitions, both of which refer to another bean:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="john-classic" class="com.example.Person">
        <property name="name" value="John Doe"/>
        <property name="spouse" ref="jane"/>
    </bean>

    <bean name="john-modern"
        class="com.example.Person"
        p:name="John Doe"
        p:spouse-ref="jane"/>

    <bean name="jane" class="com.example.Person">
        <property name="name" value="Jane Doe"/>
    </bean>
</beans>

This example not only contains a property value using the p-namespace, but also uses a special format to declare the property reference. The first bean definition uses to create a reference from bean john to bean jane, and the second bean definition uses P: House ref = "Jane" as an attribute to do exactly the same work. In this case, sparse is the property name, and the - ref section indicates that this is not a direct value, but a reference to another bean.

    p-Namespaces are not as good as standard XML Flexible format.
    For example, declaring a property reference is in the same format as Ref The attribute at the end conflicts with the standard XML The format will not.
    We recommend that you carefully choose your method and communicate with your team members,
    To avoid generating all three methods at the same time XML file.

	The p-namespace is not as flexible as the standard XML format. 
	For example, the format for declaring property references clashes 
	with properties that end in Ref,whereas the standard XML format does not.
	We recommend that you choose your approach carefully 
	and communicate this to your team members to avoid producing XML documents
	that use all three approaches at the same time.
	
	I didn't understand this paragraph. I tested it here Ref The attribute at the end can also be used p:xxxRef-ref
XML shortcut with c-namespace

Similar to XML shortcuts using p-namespace, the c-namespace introduced in Spring 3.1 allows constructor parameters to be configured using inline attributes instead of nested constructor parameter elements. To put it bluntly, p-namespace replaces property and c-namespace replaces constructor arg

The following example uses the c: namespace to perform the same operation as constructor based dependency injection:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:c="http://www.springframework. Org / schema / C "<! -- add this article -- >
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>

    <!-- Traditional declaration with optional parameter names -->
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg name="thingTwo" ref="beanTwo"/>
        <constructor-arg name="thingThree" ref="beanThree"/>
        <constructor-arg name="email" value="something@somewhere.com"/>
    </bean>

    <!-- With parameter name c-Namespace declaration -->
    <bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
        c:thingThree-ref="beanThree" c:email="something@somewhere.com"/>

</beans>

For rare cases where the constructor parameter name is not available (usually when there is no debugging information when compiling bytecode), you can use fallback to the parameter index, as shown below:

<bean id="beanOne" class="x.y.ThingOne" c:_0-ref="beanTwo" c:_1-ref="beanThree"
    c:_2="something@somewhere.com"/>
The composite attribute name embeds another bean in one bean and needs to assign a value to the internal bean

When setting bean properties, you can use composite or nested property names as long as all components of the path (except the final property name) are not empty. Consider the following bean definitions:

<bean id="something" class="things.ThingOne">
    <property name="fred.bob.sammy" value="123" />
</bean>


Stated something bean have fred Property that has bob Properties,
bob Attribute has sammy Characteristics, and finally sammy Property is set to a value of 123.  
something bean of fred Properties and fred of bob Property in construction bean After that, you must not null.   
Otherwise, it will cause NullPointerException. 
1.4.3. Using dependencies on

If a bean is a dependency of another bean, it usually means setting one bean as a property of another bean. Typically, you can do this using elements in XML based configuration metadata.
However, sometimes dependencies between beans are less direct. An example is when a static initializer in a class needs to be triggered, such as for database driver registration. The dependencies on attribute can explicitly force the initialization of one or more beans before initializing the beans that use this element. The following example uses this dependencies on property to represent dependencies on a single bean:

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

To express a dependency on multiple bean s, you need to separate multiple names with commas

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
depends-on You can specify the initialization time dependency,
You can also specify the corresponding destruction time dependency(Only in single case bean in). Dependent bean Will be later than dependency bean Later destroyed

<bean id="serviceOneRef" name="serviceOneName" class="org.springframework.example.service.ServiceOne"
		  destroy-method="destroyed"/>
    public void destroyed(){
		System.out.println("ServiceOne destroy");
	}
	
<bean id="serviceTwo" class="org.springframework.example.service.ServiceTwo"
		  p:name="asdfasdf"  depends-on="serviceOneRef"
		  destroy-method="destroyed" />
    public void destroyed(){
		System.out.println("serviceTwo destroy");
	}
		  
console: 
    serviceTwo destroy
    ServiceOne destroy
1.4.4. Lazy load bean

By default, the ApplicationContext implementation eagerly creates and configures all singleton bean s as part of the initialization process. In general, this pre instantiation is desirable because errors in the configuration or surrounding environment are discovered immediately, rather than hours or even days later.
When this behavior is inappropriate, you can prevent pre instantiation of singleton beans by marking the bean definition as delayed initialization. A bean that delays initialization tells the IoC container to create a bean instance when it is first requested (not at startup).

In XML, this behavior is controlled by the lazy init attribute of the element, as shown in the following example:

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.something.AnotherBean"/>

When ApplicationContext uses the previous configuration,
Lazy beans will not be pre instantiated eagerly when ApplicationContext starts,
not. Lazy beans are eagerly pre instantiated.

However, when the lazy loaded bean is a dependency of the non lazy loaded singleton bean, the ApplicationContext will create the lazy loaded bean at startup because it must meet the singleton dependency.

You can also batch set lazy load bean s by using the default lazy init of the element

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>
1.4.5. automatic assembly

The Spring container can automatically assemble the relationship between collaboration bean s.
Automatic assembly has the following advantages:

  • Automatic assembly can greatly reduce the need to specify properties or constructor parameters.
  • With the development of objects, automatic assembly can update the configuration. For example, if you need to add a dependency to a class, the dependency can be satisfied automatically without modifying the configuration. Therefore, automatic assembly is particularly useful in the development process without worrying about the choice of switching to explicit wiring when the contemporary code library becomes more stable.

When using XML based configuration metadata, you can use the autowire attribute of the element to specify the automatic assembly mode for the bean definition. The automatic assembly function has four modes. You can specify auto assembly for each bean, so you can choose which assembly to auto assemble. The following table describes four automatic assembly modes:

pattern explain
no (default) there is no automatic assembly. If you want to reference other beans, they must be defined by the ref element.
For larger deployments, it is not recommended to change the default settings,
Because explicitly specifying the bean s that need to be referenced provides better control and clarity.
To some extent, it records the structure of the system.
byName Auto assemble by attribute name.
Spring looks for bean s with the same name as the properties that need to be implemented automatically.
For example, if a bean defines that the autowire mode is set to byName,
And it contains a master attribute (that is, it has a setMaster(..) Method)
Then Spring will find a bean definition named master,
And use it to set this property.
The attribute name is mainly determined according to the set method. If you have a master attribute,
But your set method is setMyMaster(..),
Then Spring will look for a bean named myMaster instead of a bean named master
byType The input parameter type applicable to the set method,
If there happens to be a bean of this attribute type in the container, the attribute is allowed to be injected automatically.
If there are multiple, a fatal exception will be thrown,
This indicates that you cannot use byType auto assembly on this bean.
If there is no matching bean, nothing happens (no properties are set).
constructor Similar to byType, but applicable to constructor parameters.
If there is no exact bean of constructor parameter type in the container, a fatal error will be raised.

Using byType or constructor auto assembly mode, you can automatically inject arrays and collections types. In this case, all automatic assembly candidates in the container that match the desired type will be provided to meet the correlation.
If the key value type of the received Map is String, you can also let Spring automatically assemble the value of the Map type, and the key value of the Map instance is the corresponding bean name.

	@Autowired
	private List<CusService> serviceLists;

	@Autowired
	private Map<String,CusService> cusServiceMap;
Limitations and disadvantages of automatic wiring

Automatic assembly works best when used consistently in a project. If auto assembly is not widely used, using it to connect one or two bean definitions may confuse some developers.

Consider the limitations and disadvantages of automatic assembly:

  • Explicit dependencies in property and construction parameter settings always override automatic assembly. You cannot automatically connect simple attributes, such as primitives (boolean,int,long, etc.), String and classes (and arrays of such simple attributes). This restriction is deliberately designed.
  • Auto assemble beans are not as precise as explicitly specifying beans. However, as pointed out in the previous table, Spring has avoided unexpected results as much as possible. The relationships between Spring managed objects are no longer explicitly documented.
  • For tools that can generate documents from the Spring container, it is impossible to generate connection information.
  • When automatically injecting dependencies, if there are multiple matching options, and if the injection type is array, collection or mapping instance, this is not a problem. However, this ambiguity cannot be solved arbitrarily for dependencies that expect to use a single value. If a bean definition is not available, a unique exception is thrown.

In the latter case, you have several options:

  • Abandon automatic assembly and support explicit routing.
  • Avoid automatic assembly by setting the autowire candidate defined by the bean to false.
  • By setting the primary of an element defined by a single bean to true, it is designated as the primary candidate bean definition.
  • Use annotation based configuration to achieve more fine-grained control. Section 1.9 will specifically explain the use of annotations.
1.Abandon automatic assembly and specify instead bean injection @Qualifier perhaps xml of ref All properties are OK
2.
    	<bean id="serviceOne"  class="org.springframework.example.service.ServiceOne" />
    	<bean id="serviceTwo"  class="org.springframework.example.service.ServiceTwo" />
    Two bean All inherit the same interface CusService´╝îIf there is automatic assembly, it is as follows
    	@Autowired
    	private CusService service;
    An error will be reported during startup
    If you give serviceOne Add attribute autowire-candidate="false" 
    	<bean id="serviceOne"  class="org.springframework.example.service.ServiceOne" autowire-candidate="false" />
    Then all automatic assembly CusService All interfaces will be assembled first serviceTwo
3.In the same situation as 2, you can also serviceTwo increase primary="true" 
        <bean id="serviceTwo"  class="org.springframework.example.service.ServiceTwo" primary="true" />
Exclude beans from auto assembly

On a per bean basis, you can exclude one bean from automatic assembly. In Spring's XML format, set the autowire candidate of the element to false. The container makes specific bean definitions unavailable to the auto assembly infrastructure (including annotation style configuration, such as @ Autowired).

autowire-candidate Attributes are designed to affect only type based automatic assembly.
It does not affect explicit references by name, even if specified bean Not marked as an automatic assembly candidate,
Explicit references are also resolved. Therefore, if the names match, the automatic assembly by name will still inject one bean. 

The element receives a patterns string in its default autowire candidates attribute, which means that the autowire candidates of all qualified beannames matched according to the patterns string will be set to true, and the unqualified ones will be set to false
Patterns strings accept one or more matching patterns, and multiple patterns strings can be separated by commas. For example, (Repository,Service,*Dao) is a composite model

The autowire candidates attribute of the bean itself is better than the default autowire candidates attribute of the bean

These techniques are useful for beans that you never want to inject into other beans through automatic assembly. This does not mean that the excluded beans themselves cannot be configured using automatic assembly. On the contrary, the bean itself is simply not a candidate for automatic connection of other beans.

	    public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";

        //Get the value of autowire candidate, which is true by default
        String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
        //Determine whether the defined current bean is default
		if (isDefaultValue(autowireCandidate)) {
		    //If it is default 
		    //Find the default autowire candidates property of the beans where the current bean is located, and find the configured patterns expression
		    //If the expression is empty, the setAutowireCandidate property value will not be processed, so the property is still true
			String candidatePattern = this.defaults.getAutowireCandidates();
			if (candidatePattern != null) {
			    //If the expression is not empty, judge whether the current beanName is within the expression range
			    //Set setAutowireCandidate to true within the scope
			    //Otherwise, set to false
				String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
				bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
			}
		}
		else {
		//If autowireCandidate is not default but true, set it to true 
		//If it is false, set it to false
			bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
		}
1.4.6. Method injection

In most application scenarios, most bean s in the container are singletons.
When a singleton Bean needs to cooperate with another singleton Bean or a non singleton Bean needs to cooperate with another non singleton Bean, you can usually handle dependencies by defining one Bean as the attribute of another Bean. There is no problem when classes with the same life cycle are injected into each other.
Problems arise when the life cycle of a bean is different. Suppose that singleton bean A needs to use non singleton (prototype) bean B, which may be used on every method call of A. The container creates singleton bean A only once, so it has only one chance to set properties. Each time a container is needed, the container cannot provide a new bean B instance for bean A.

One solution is to abandon some control reversals. You can make bean A know the container by implementing the interface ApplicationContextAware and making container A need the call of container B to request (usually new) bean B instances every time. The following example shows this method: ApplicationContextAware getBean("B")

// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;

// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CommandManager implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Object process(Map commandState) {
        // grab a new instance of the appropriate Command
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    protected Command createCommand() {
        // notice the Spring API dependency!
        return this.applicationContext.getBean("command", Command.class);
    }

    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

The previous content is not ideal because the business code knows and is coupled to the Spring framework. Method injection is an advanced feature of the Spring IoC container that allows you to handle this use case cleanly.

You can here Blog entry Learn more about method injection motivation in.

Lookup Method injection

Lookup Method injection refers to the ability of the container to override the method on the container managed bean and return the search result of another named bean in the container. Lookup usually involves prototype beans, as described in the previous section. The Spring framework implements this method injection by dynamically generating subclasses covering the method using bytecode generation from the CGLIB library.

  • To make this dynamic subclass work, the class of Spring bean container subclass cannot be final, and the method to be covered cannot be final.
  • Unit testing a class with abstract methods requires you to create subclasses of the class and provide stub implementation of the abstract methods.
  • Specific methods are also necessary for component scanning, which requires specific classes to pick up.
  • Another key limitation is that the Lookup Method cannot work with factory methods, especially with the @ Bean method in the configuration class, because in this case, the container is not responsible for creating instances, so it cannot dynamically create run-time generated subclasses.

For the classes in the previous code snippet of CommandManager, the Spring container dynamically overrides the implementation of the createCommand() method. The CommandManager class does not have any Spring dependencies, as shown below:

package fiona.apple;
public abstract class CommandManager {

    public Object process(Object commandState) {
        // Get a new instance of the appropriate command interface
        Command command = createCommand();
        // Set the state on the (hopefully brand new) command instance
        command.setState(commandState);
        return command.execute();
    }

    // Where is the implementation class???
    protected abstract Command createCommand();
}

In the client class containing the method to be injected (commandmanager in this example), the method to be injected needs the following signature:

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

If the method is abstract, the dynamically generated subclass will implement the method. Otherwise, the dynamically generated subclass will override the concrete methods defined in the original class. Consider the following examples:

<!-- Stateful deployment as a prototype bean(Non single case)-->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as required -->
</bean>

<!-- commandProcessor use statefulCommandHelper-->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>

The bean identified as commandManager calls its own createCommand() method when it needs a new instance of myCommand bean. If you want to deploy myCommand bean as a prototype, you must carefully confirm your requirements. If it is a singleton, the same myCommand bean instance is returned every time.

Alternatively, in the annotation based component model, you can declare a Lookup method through the @ Lookup annotation, as shown in the following example:

public abstract class CommandManager {
    public Object process(Object commandState) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup("myCommand")
    protected abstract Command createCommand();
}

Depending on the declared type of the target bean, you can use the following methods:

public abstract class CommandManager {
    public Object process(Object commandState) {
        MyCommand command = createCommand();
        command.setState(commandState);
        return command.execute();
    }

    @Lookup
    protected abstract MyCommand createCommand();
}

Note that you should usually declare such annotated lookup methods using specific stub implementations so that they are compatible with Spring's component scanning rules, where abstract classes are ignored by default. This restriction does not apply to bean classes that are explicitly registered or explicitly imported.

Targets with different access ranges bean Another way is ObjectFactory/ Provider Injection point( https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-scopes-other-injection). 


You may also find ServiceLocatorFactoryBean(stay org.springframework.beans.factory.config Useful in packaging.
Any method replacement

The form of method replacement injection is the ability to replace any method in a managed bean with another method. This is not commonly used. You can skip the rest of this section and wait until you really need this function.

For xml based configuration metadata, you can use the replaced method element to replace the existing method implementation of one deployed bean with another. Consider the following class, which has a method called computeValue. We want to override it:

public class MyValueCalculator {
    public String computeValue(String input) {
        // some real code...
    }
}

Realize the org springframework. beans. factory. support. The class of methodreplace interface provides a new method definition, as shown in the following example:

/**
 *Used to overwrite the existing computeValue(String input)
 *Implemented in MyValueCalculator
 */
public class ReplacementComputeValue implements MethodReplacer {

    public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
        //Get the input value, use it, and return the calculation result
        String input = (String) args[0];
        ...
        return ...;
    }
}

The Bean definition used to deploy the original class and specify method overrides is similar to the following example:

<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
    <replaced-method name="computeValue" replacer="replacementComputeValue">
        <arg-type>String</arg-type>
    </replaced-method>
</bean>

<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>

You can use one or more elements within an element to indicate the method signature of the method to override. Parameter signing is only required if the method is overloaded and there are multiple variants in the class. For convenience, the type string of a parameter can be a substring of a fully qualified type name.
For example, all of the following are Java Lang.string matches:

java.lang.String
String
Str

Because the number of parameters is usually sufficient to distinguish each possible choice, this shortcut can save a lot of input by letting you type only the shortest string that matches the parameter type

Posted by stbalaji2u on Tue, 17 May 2022 20:50:43 +0300