关闭

3. IoC 和DI

179人阅读 评论(0) 收藏 举报
分类:

IoC 可分为两种子类型 :Dependency Injection and Dependency Lookup.


IoC的类型

Dependency Lookup的实现:Dependency Pull 和Contextualized Dependency Lookup (CDL)
Dependency Injection的实现:Constructor and Setter Dependency Injection.

Dependency Pull



Listing 3-1. Dependency Pull in Spring
package com.apress.prospring4.ch3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DependencyPull {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext
("META-INF/spring/app-context.xml");
MessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}

Contextualized Dependency Lookup



Listing 3-2. Component Interface for CDL
package com.apress.prospring4.ch3;
public interface ManagedComponent {
void performLookup(Container container);
}
Listing 3-3. A Simple Container Interface
package com.apress.prospring4.ch3;
public interface Container {
Object getDependency(String key);
}
Listing 3-4. Obtaining Dependencies in CDL
package com.apress.prospring4.ch3;
public class ContextualizedDependencyLookup implements ManagedComponent {
private Dependency dependency;
@Override
public void performLookup(Container container) {
this.dependency = (Dependency) container.getDependency("myDependency");
}
@Override
public String toString() {
return dependency.toString();
}
}
Note that in Listing 3-4, Dependency is an empty class.

Constructor Dependency Injection

Listing 3-5. Constructor Dependency Injection
package com.apress.prospring4.ch3;
public class ConstructorInjection {
private Dependency dependency;
public ConstructorInjection(Dependency dependency) {
this.dependency = dependency;
}
@Override
public String toString() {
return dependency.toString();
}
}

Setter Dependency Injection

Listing 3-6. Setter Dependency Injection
package com.apress.prospring4.ch3;
public class SetterInjection {
private Dependency dependency;
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
@Override
public String toString() {
return dependency.toString();
}
}


Inversion of Control in Spring





Dependency Injection in Spring

Beans and BeanFactories

DI的核心BeanFactory interface
bean is used  to refer to any component managed by the container

bean的配置使用BeanDefinition interface的实例表示,BeanFactory的实现经常实现了BeanDefinitionReader interface

使用PropertiesBeanDefinitionReader or XmlBeanDefinitionReader 从配置文件读取BeanDefinition 


BeanFactory Implementations

Listing 3-10. The Oracle Interface
package com.apress.prospring4.ch3;
public interface Oracle {
String defineMeaningOfLife();
}
Listing 3-11. A Simple Oracle Interface Implementation
package com.apress.prospring4.ch3;
public class BookwormOracle implements Oracle {
@Override
public String defineMeaningOfLife() {
return "Encyclopedias are a waste of money - use the Internet";
}
}
Listing 3-12. Using BeanFactory
package com.apress.prospring4.ch3;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
public class XmlConfigWithBeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader rdr = new XmlBeanDefinitionReader(factory);
rdr.loadBeanDefinitions(new
ClassPathResource("META-INF/spring/xml-bean-factory-config.xml"));
Oracle oracle = (Oracle) factory.getBean("oracle");
System.out.println(oracle.defineMeaningOfLife());
}
}
Listing 3-13. Simple Spring XML Configuration
<?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.xsd">
<bean id="oracle" name="wiseworm" class="com.apress.prospring4.ch3.BookwormOracle"/>
</beans>

ApplicationContext

Spring supports the bootstrapping of ApplicationContext by manual coding,or in a web container environment via the
ContextLoaderListener.

Configuring ApplicationContext


Setting Spring Configuration Options

xml 或者annotations或者混合

Basic Configuration Overview

Listing 3-14. Simple Spring XML Configuration
<?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.xsd">
</beans>

Listing 3-15. Spring XML Configuration with Annotation Support
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.apress.prospring4.ch3.annotation" />
</beans>
The <context:component-scan> tag tells Spring to scan the code for injectable beans annotated with @Component,
@Controller, @Repository, and @Service as well as supporting the @Autowired and @Inject annotations under the
package (and all its subpackages) specified.
可以使用 逗号,分号 ,空格分隔多个包。

Listing 3-16. Spring XML Configuration Component Scan
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.apress.prospring4.ch3.annotation" >
<context:exclude-filter type="assignable" expression="com.example.NotAService"/>
</context:component-scan>
</beans>
也可以使用include filter
类型可以是annotation, regex, assignable, AspectJ, or custom(implements org.springframework.core.type.filter.TypeFilter)

Declaring Spring Components

Listing 3-18. Declare Spring Beans (XML)
<?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.xsd">
<bean id="messageRenderer"
class="com.apress.prospring4.ch3.xml.StandardOutMessageRenderer"/>
<bean id="messageProvider"
class="com.apress.prospring4.ch3.xml.HelloWorldMessageProvider"/>
</beans>

Listing 3-19. Declare Spring Beans (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Service;
import com.apress.prospring4.ch3.MessageRenderer;
@Service("messageRenderer")
public class StandardOutMessageRenderer implements MessageRenderer {..
...
}
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Service;
import com.apress.prospring4.ch3.MessageProvider;
@Service("messageProvider")
public class HelloWorldMessageProvider implements MessageProvider {
@Override
public String getMessage() {
return "Hello World!";
}
}

Listing 3-20. Declare Spring Beans (Testing)
package com.apress.prospring4.ch3;
import org.springframework.context.support.GenericXmlApplicationContext;
public class DeclareSpringComponents {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:app-context-xml.xml");
ctx.refresh();
MessageProvider messageProvider = ctx.getBean("messageProvider",
MessageProvider.class);
System.out.println(messageProvider.getMessage());
}
}





Listing 3-21. XML Configuration (app-context-xml.xml)
<?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.xsd">
<bean id="messageProvider"
class="com.apress.prospring4.ch3.xml.HelloWorldMessageProvider"/>
</beans>
Listing 3-22. Annotation Configuration (app-context-annotation.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="com.apress.prospring4.ch3.annotation"/>
</beans>

Using Setter Injection

Listing 3-23. Setter Injection (XML)
<?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.xsd">
<bean id="messageRenderer"
class="com.apress.prospring4.ch3.xml.StandardOutMessageRenderer">
<property name="messageProvider" ref="messageProvider"/>
</bean>
<bean id="messageProvider"
class="com.apress.prospring4.ch3.xml.HelloWorldMessageProvider"/>
</beans>

Listing 3-24. Setter Injection (XML)  // p namespace
<?xml version="1.0" encoding="UTF-8"?>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="messageRenderer"
class="com.apress.prospring4.ch3.xml.StandardOutMessageRenderer"
p:messageProvider-ref="messageProvider"/>
<bean id="messageProvider"
class="com.apress.prospring4.ch3.xml.HelloWorldMessageProvider"/>
</beans>

使用标注add an @Autowired annotation to the setter method,也可以使用@Resource(name="messageProvider")
Listing 3-25. Setter Injection (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Service;
import com.apress.prospring4.ch3.MessageRenderer;
import com.apress.prospring4.ch3.MessageProvider;
@Service("messageRenderer")
public class StandardOutMessageRenderer implements MessageRenderer {
private MessageProvider messageProvider;
@Override
public void render() {
if (messageProvider == null) {
throw new RuntimeException(
"You must set the property messageProvider of class:"
+ StandardOutMessageRenderer.class.getName());
}
System.out.println(messageProvider.getMessage());
}
@Override
@Autowired
public void setMessageProvider(MessageProvider provider) {
this.messageProvider = provider;
}
@Override
public MessageProvider getMessageProvider() {
return this.messageProvider;
}
}

Using Constructor Injection

Listing 3-27. The ConfigurableMessageProvider Class (XML)
package com.apress.prospring4.ch3.xml;
import com.apress.prospring4.ch3.MessageProvider;
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
public ConfigurableMessageProvider(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
使用 <constructor-arg> tag  有多个时,可以使用索引(从0开始)
Listing 3-28. Using Constructor Injection (XML)
<?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.xsd">
	<bean id="messageProvider"
		class="com.apress.prospring4.ch3.xml.ConfigurableMessageProvider">
		<constructor-arg value="Configurable message" />
	</bean>
</beans>

也可以使用c namespace

<?xml version="1.0" encoding="UTF-8"?>
<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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="messageProvider"
		class="com.apress.prospring4.ch3.xml.ConfigurableMessageProvider"
		c:message="This is a configurable message" />
</beans>

使用标注   use the @Autowired annotation in the target bean’s constructor method,@Value, to define the value to be injected into the constructor
Listing 3-29. Using Constructor Injection (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import com.apress.prospring4.ch3.MessageProvider;
@Service("messageProvider")
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
@Autowired
public ConfigurableMessageProvider(@Value("Configurable message") String message) {
this.message = message;
}
@Override
public String getMessage() {
return this.message;
}
}


混合, bean的id和构造器参数相同
Listing 3-30. Using Constructor Injection (Annotation)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:c="http://www.springframework.org/schema/c"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="com.apress.prospring4.ch3.annotation" />
	<bean id="message" class="java.lang.String" c:_0="This is a configurable message" />
</beans>
Listing 3-31. Using Constructor Injection (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.apress.prospring4.ch3.MessageProvider;
@Service("messageProvider")
public class ConfigurableMessageProvider implements MessageProvider {
private String message;
@Autowired
public ConfigurableMessageProvider(String message) {
this.message = message;
}
@Override
public String getMessage() {
return this.message;
}
}

Using Injection Parameters

<property> and <constructor-args> tags

Injecting Simple Values

Listing 3-37. Injecting Simple Values (XML)
package com.apress.prospring4.ch3.xml;
import org.springframework.context.support.GenericXmlApplicationContext;
public class InjectSimple {
private String name;
private int age;
private float height;
private boolean programmer;
private Long ageInSeconds;
。。。
set get...
}
<pre name="code" class="html">Listing 3-38. Configuring Simple Value Injection
<?xml version="1.0" encoding="UTF-8"?>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="injectSimple" class="com.apress.prospring4.ch3.xml.InjectSimple"
		p:name="Chris Schaefer" p:age="32" p:height="1.778" p:programmer="true"
		p:ageInSeconds="1009843200" />
</beans>



Listing 3-39. Injecting Simple Values (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.stereotype.Service;
@Service("injectSimple")
public class InjectSimple {
@Value("Chris Schaefer")
private String name;
@Value("32")
private int age;
@Value("1.778")
private float height;
@Value("true")
private boolean programmer;
@Value("1009843200")
private Long ageInSeconds
...}

Injecting Values by Using SpEL

Listing 3-40. Injecting Values by Using SpEL (XML)
package com.apress.prospring4.ch3.xml;
public class InjectSimpleConfig {
private String name = "Chris Schaefer";
private int age = 32;
private float height = 1.778f;
private boolean programmer = true;
private Long ageInSeconds = 1009843200L;
...set get}
Listing 3-41. Injecting Values by Using SpEL (XML)
<?xml version="1.0" encoding="UTF-8"?>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="injectSimpleConfig" class="com.apress.prospring4.ch3.xml.InjectSimpleConfig"/>
<bean id="injectSimpleSpel" class="com.apress.prospring4.ch3.xml.InjectSimpleSpel"
p:name="#{injectSimpleConfig.name}"
p:age="#{injectSimpleConfig.age}"
p:height="#{injectSimpleConfig.height}"
p:programmer="#{injectSimpleConfig.programmer}"
p:ageInSeconds="#{injectSimpleConfig.ageInSeconds}"/>
</beans>


标注形式:
Listing 3-43. Injecting Values by Using SpEL (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.stereotype.Service;
@Service("injectSimpleSpel")
public class InjectSimpleSpel {
@Value("#{injectSimpleConfig.name}")
private String name;
@Value("#{injectSimpleConfig.age + 1}")
private int age;
@Value("#{injectSimpleConfig.height}")
private float height;
@Value("#{injectSimpleConfig.programmer}")
private boolean programmer;
@Value("#{injectSimpleConfig.ageInSeconds}")
private Long ageInSeconds;
。。。}
Listing 3-44. InjectSimpleConfig Class (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Component;
@Component("injectSimpleConfig")
public class InjectSimpleConfig {
private String name = "John Smith";
private int age = 35;
private float height = 1.78f;
private boolean programmer = true;
private Long ageInSeconds = 1103760000L;
}

Practically, @Service is a specialization of @Component, which indicates that the
annotated class is providing a business service to other layers within the application.


Injecting Beans in the Same XML Unit

Listing 3-46. Configuring Bean Injection
<?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.xsd">
	<bean id="oracle" name="wiseworm" class="com.apress.prospring4.ch3.BookwormOracle" />
	<bean id="injectRef" class="com.apress.prospring4.ch3.xml.InjectRef">
		<property name="oracle">
			<ref bean="oracle" />
		</property>
	</bean>
</beans>
When you use the local attribute, it means that the <ref> tag only looks at
the bean’s id and never at any of its aliases.
Listing 3-47. Injecting Using Bean Aliases
<?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.xsd">
	<bean id="oracle" name="wiseworm" class="com.apress.prospring4.ch3.BookwormOracle" />
	<bean id="injectRef" class="com.apress.prospring4.ch3.xml.InjectRef">
		<property name="oracle">
			<ref bean="wiseworm" />
		</property>
	</bean>
</beans>

Injection and ApplicationContext Nesting

Listing 3-48. Nesting GenericXmlApplicationContext
package com.apress.prospring4.ch3;
import org.springframework.context.support.GenericXmlApplicationContext;
public class HierarchicalAppContextUsage {
public static void main(String[] args) {
GenericXmlApplicationContext parent = new GenericXmlApplicationContext();
parent.load("classpath:META-INF/spring/parent.xml");
parent.refresh();
GenericXmlApplicationContext child = new GenericXmlApplicationContext();
child.load("classpath:META-INF/spring/app-context-xml.xml");
child.setParent(parent);
child.refresh();
SimpleTarget target1 = (SimpleTarget) child.getBean("target1");
SimpleTarget target2 = (SimpleTarget) child.getBean("target2");
SimpleTarget target3 = (SimpleTarget) child.getBean("target3");
System.out.println(target1.getVal());
System.out.println(target2.getVal());
System.out.println(target3.getVal());
}
}


Listing 3-50. Parent ApplicationContext Configuration
<?xml version="1.0" encoding="UTF-8"?>
<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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="injectBean" class="java.lang.String" c:_0="Bean In Parent" />
	<bean id="injectBeanParent" class="java.lang.String" c:_0="Bean In Parent" />
</beans>

Listing 3-51. Child ApplicationContext Configuration
<?xml version="1.0" encoding="UTF-8"?>
<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"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="target1" class="com.apress.prospring4.ch3.SimpleTarget"
		p:val-ref="injectBeanParent" />
	
<span style="white-space:pre">	</span><bean id="target2" class="com.apress.prospring4.ch3.SimpleTarget"
		p:val-ref="injectBean" />    // 自己
	
<span style="white-space:pre">	</span><bean id="target3" class="com.apress.prospring4.ch3.SimpleTarget">
		<property name="val">
			<ref parent="injectBean" />  //父
		</property>
	</bean>
	<bean id="injectBean" class="java.lang.String" c:_0="Child In Bean" />
</beans>
Bean In Parent
Bean In Child
Bean In Parent


Using Collections for Injection

Listing 3-52. Collection Injection (XML)
package com.apress.prospring4.ch3.xml;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.context.support.GenericXmlApplicationContext;
public class CollectionInjection {
private Map<String, Object> map;
private Properties props;
private Set set;
private List list;
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.load("classpath:META-INF/spring/app-context-xml.xml");
ctx.refresh();
CollectionInjection instance = (CollectionInjection) ctx.getBean("injectCollection");
instance.displayInfo();
}
。。。set}

Listing 3-53. Configuring Collection Injection (XML)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<span style="white-space:pre">	</span>xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<span style="white-space:pre">	</span>xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<span style="white-space:pre">	</span><bean id="oracle" name="wiseworm"
<span style="white-space:pre">		</span>class="com.apress.prospring4.ch3.xml.BookwormOracle" />
<span style="white-space:pre">	</span><bean id="injectCollection" class="com.apress.prospring4.ch3.xml.CollectionInjection">
<span style="white-space:pre">		</span><property name="map">
<span style="white-space:pre">			</span><map>
<span style="white-space:pre">				</span><entry key="someValue">
<span style="white-space:pre">					</span><value>Hello World!</value>
<span style="white-space:pre">				</span></entry>
<span style="white-space:pre">				</span><entry key="someBean">
<span style="white-space:pre">					</span><ref local="oracle" />
<span style="white-space:pre">				</span></entry>
<span style="white-space:pre">			</span></map>
<span style="white-space:pre">		</span></property>
<span style="white-space:pre">		</span><property name="props">
<span style="white-space:pre">			</span><props>
<span style="white-space:pre">				</span><prop key="firstName">Chris</prop>   //字符串
<span style="white-space:pre">				</span><prop key="secondName">Schaefer</prop>
<span style="white-space:pre">			</span></props>
<span style="white-space:pre">		</span></property>
<span style="white-space:pre">		</span><property name="set">
<span style="white-space:pre">			</span><set>
<span style="white-space:pre">				</span><value>Hello World!</value>
<span style="white-space:pre">				</span><ref local="oracle" />
<span style="white-space:pre">			</span></set>
<span style="white-space:pre">		</span></property>
<span style="white-space:pre">		</span><property name="list">
<span style="white-space:pre">			</span><list>
<span style="white-space:pre">				</span>)
<span style="white-space:pre">				</span><value>Hello World!</value>
<span style="white-space:pre">				</span><ref local="oracle" />
<span style="white-space:pre">			</span></list>
<span style="white-space:pre">		</span></property>
<span style="white-space:pre">	</span></bean>
</beans>  
map、set、list可嵌套



Listing 3-56. Configuring Collection Injection (Annotation)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	
<span style="white-space:pre">	</span>xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
	<context:annotation-config />
	<context:component-scan base-package="com.apress.prospring4.ch3.annotation" />
	<util:map id="map" map-class="java.util.HashMap">
		<entry key="someValue">
			<value>Hello World!</value>
		</entry>
		<entry key="someBean">
			<ref bean="oracle" />
		</entry>
	</util:map>
	<util:properties id="props">
		<prop key="firstName">Chris</prop>
		<prop key="secondName">Schaefer</prop>
	</util:properties>
	<util:set id="set">
		<value>Hello World!</value>
		<ref bean="oracle" />
	</util:set>
	<util:list id="list">
		<value>Hello World!</value>
		<ref bean="oracle" />
	</util:list>
</beans>


Listing 3-57. The BookwormOracle Class (Annotation)
package com.apress.prospring4.ch3.annotation;
import org.springframework.stereotype.Service;
import com.apress.prospring4.ch3.Oracle;
@Service("oracle")
public class BookwormOracle implements Oracle {
@Override
public String defineMeaningOfLife() {
return "Encyclopedias are a waste of money - use the Internet";
}
}

Listing 3-58. Configuring Collection Injection (Annotation) ";
package com.apress.prospring4.ch3.annotation;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.stereotype.Service;
import org.springframework.context.support.GenericXmlApplicationContext;
import javax.annotation.Resource;
@Service("injectCollection")
public class CollectionInjection {
@Resource(name="map")
private Map<String, Object> map;
@Resource(name="props")
private Properties props;
@Resource(name="set")
private Set set;
@Resource(name="list")
private List list;
。。。}

for collection type injection, we have to explicitly instruct Spring to
perform injection by specifying the bean name, which the @Resource annotation supports.

Using Method Injection

Lookup Method Injection and Method Replacement.

Lookup Method Injection

用于解决生命周期不匹配,singleton对nonsingleton每次需要一个新实例,也可以achieve this by having the singleton bean implement the ApplicationContextAware interface

Listing 3-59. The MyHelper Bean
package com.apress.prospring4.ch3;             //nonsingleton
public class MyHelper {
public void doSomethingHelpful() {
// do something!
}
}

Listing 3-60. The DemoBean Interface
package com.apress.prospring4.ch3;
public interface DemoBean {
MyHelper getMyHelper();
void someOperation();
}

Listing 3-61. The StandardLookupDemoBean Class
package com.apress.prospring4.ch3;
public class StandardLookupDemoBean implements DemoBean {
private MyHelper myHelper;<span style="white-space:pre">			</span>//设置注入
public void setMyHelper(MyHelper myHelper) {
this.myHelper = myHelper;
}
@Override
public MyHelper getMyHelper() {
return this.myHelper;
}
@Override
public void someOperation() {
myHelper.doSomethingHelpful();
}
}

Listing 3-62. The AbstractLookupDemoBean Class   
package com.apress.prospring4.ch3;
public abstract class AbstractLookupDemoBean implements DemoBean {
public abstract MyHelper getMyHelper();<span style="white-space:pre">			</span><span style="font-family: Arial, Helvetica, sans-serif;">//使用</span><span style="white-space:pre">	Method Injection </span>
@Override
public void someOperation() {
getMyHelper().doSomethingHelpful();
}
}

Listing 3-63. Configuring Lookup Method Injection
<?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.xsd">
	<bean id="helper" class="com.apress.prospring4.ch3.MyHelper"
		scope="prototype" />
	<bean id="abstractLookupBean" class="com.apress.prospring4.ch3.AbstractLookupDemoBean">     //配置
		
<span style="white-space:pre">		</span><lookup-method name="getMyHelper" bean="helper" />
	</bean>
	<bean id="standardLookupBean" class="com.apress.prospring4.ch3.StandardLookupDemoBean">
		<property name="myHelper">
			<ref bean="helper" />
		</property>
	</bean>
</beans>

Method Replacement

you can replace the implementation of any method on any beans arbitrarily without having to change the source of the bean you are modifying
 
Listing 3-65. The ReplacementTarget Class
package com.apress.prospring4.ch3;
public class ReplacementTarget {
public String formatMessage(String msg) {
return "<h1>" + msg + "</h1>";
}
public String formatMessage(Object msg) {
return "<h1>" + msg + "</h1>";
}
}
方法替换 应implementation of the MethodReplacer interface
Listing 3-66. Implementing MethodReplacer
package com.apress.prospring4.ch3;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
public class FormatMessageReplacer implements MethodReplacer {
@Override
public Object reimplement(Object arg0, Method method, Object[] args)
throws Throwable {
if (isFormatMessageMethod(method)) {
String msg = (String) args[0];
return "<h2>" + msg + "</h2>";
} else {
throw new IllegalArgumentException("Unable to reimplement method "
+ method.getName());
}
}
private boolean isFormatMessageMethod(Method method) {
if (method.getParameterTypes().length != 1) {
return false;
}
if (!("formatMessage".equals(method.getName()))) {
return false;
}
if (method.getReturnType() != String.class) {
return false;
}
if (method.getParameterTypes()[0] != String.class) {
return false;
}
return true;
}<pre name="code" class="html">


Listing 3-67. Configuring Method Replacement
<?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.xsd">
	<bean id="methodReplacer" class="com.apress.prospring4.ch3.FormatMessageReplacer" />
	<bean id="replacementTarget" class="com.apress.prospring4.ch3.ReplacementTarget">
		
<span style="white-space:pre">		</span><replaced-method name="formatMessage" replacer="methodReplacer">
			<arg-type>String</arg-type>   //支持匹配 java.lang.String and also to java.lang.StringBuffer
		</replaced-method>
	</bean>
	<bean id="standardTarget" class="com.apress.prospring4.ch3.ReplacementTarget" />
</beans>

Understanding Bean Naming

id-》 name-》 class

Bean Name Aliasing

Listing 3-70. Configuring Multiple Bean Names
<?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.xsd">
	<bean id="name1" name="name2 name3,name4;name5" class="java.lang.String" />     // 1
	<alias name="name1" alias="name6" /><span style="white-space:pre">						</span>// 2
</beans>

Understanding Bean Instantiation Mode

By default, all beans in Spring are singletons.

In reality, the Singleton pattern is actually two patterns in one. The first, and desired, pattern involves
maintenance of a single instance of an object. The second, and less desirable, is a pattern for object lookup that
completely removes the possibility of using interfaces.

instantiation mode agnostic. This is a very powerful concept. If you start off with an object that is a singleton but then
discover it is not really suited to multithread access, you can change it to a nonsingleton (prototype) without affecting
any of your application code.

Choosing an Instantiation Mode

In general, singletons should be used in the following scenarios:
  • Shared objects with no state:
  • Shared object with read-only state:
  • Shared object with shared state:
  • High-throughput objects with writable state:
using nonsingletons in the following scenarios:
  • Objects with writable state:
  • Objects with private state:

Implementing Bean Scopes

  • singleton
  • prototype
  • Request:
  • Session:
  • Global session: For portlet-based web applications. The global session scope beans can be
    shared among all portlets within the same Spring MVC–powered portal application
  • Thread: A new bean instance will be created by Spring when requested by a new thread,
    while for the same thread, the same bean instance will be returned. Note that this scope is not
    registered by default.
  • Custom: Custom bean scope that can be created by implementing the interface
    org.springframework.beans.factory.config.Scope and registering the custom scope in
    Spring’s configuration (for XML, use the class org.springframework.beans.factory.config.
    CustomScopeConfigurer).

Resolving Dependencies

Listing 3-75. Manually Defining Dependencies
<bean id="beanA" class="com.apress.prospring4.ch3.BeanA" depends-on="beanB"/>
<bean id="beanB" class="com.apress.prospring4.ch3.BeanB"/>

In this configuration, we are asserting that bean beanA depends on bean beanB. Spring takes this into
consideration when instantiating the beans and ensures that beanB is created before beanA.

Autowiring Your Bean

Modes of Autowiring

Spring supports five modes for autowiring: byName, byType, constructor, default, and no (which is the default).

When using byName autowiring, Spring attempts to wire each property to a bean of the same name. So, if the target
bean has a property named foo and a foo bean is defined in the ApplicationContext, the foo bean is assigned to the
foo property of the target.
When using byType autowiring, Spring attempts to wire each of the properties on the target bean by automatically
using a bean of the same type in ApplicationContext. So, if you have a property of type String on the target bean,
and a bean of type String in ApplicationContext, then Spring wires the String bean to the target bean’s String
property. If you have more than one bean of the same type, in this case String, in the same ApplicationContext,
then Spring is unable to decide which one to use for the autowiring and throws an exception
(of type org.springframework.beans.factory.NoSuchBeanDefinitionException).
The constructor autowiring mode functions just like byType wiring, except that it uses constructors rather than
setters to perform the injection. Spring attempts to match the greatest numbers of arguments it can in the constructor.
So, if your bean has two constructors, one that accepts a String and one that accepts a String and an Integer,
and you have both a String and an Integer bean in your ApplicationContext, Spring uses the two-argument
constructor.
In default mode, Spring will choose between constructor and byType modes automatically. If your bean has a
default (no-arguments) constructor, Spring uses byType; otherwise, it uses constructor.


Listing 3-76. Configuring Autowiring
<?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.xsd">
	<bean id="foo" class="com.apress.prospring4.ch3.Foo" />
	<bean id="bar1" class="com.apress.prospring4.ch3.Bar" />
	<bean id="targetByName" autowire="byName"
		class="com.apress.prospring4.ch3.xml.Target" lazy-init="true" />
	<bean id="targetByType" autowire="byType"
		class="com.apress.prospring4.ch3.xml.Target" lazy-init="true" />
	<bean id="targetConstructor" autowire="constructor"
		class="com.apress.prospring4.ch3.xml.Target" lazy-init="true" />
</beans>

When to Use Autowiring

Using byName seems like a good idea, but it may lead you to give your classes artificial property names so that you can
take advantage of the autowiring functionality. The whole idea behind Spring is that you can create your classes as
you like and have Spring work for you, not the other way around. You may be tempted to use byType until you realize
that you can have only one bean for each type in your ApplicationContext—a restriction that is problematic when
you need to maintain beans with different configurations of the same type. The same argument applies to the use of
constructor autowiring.
In some cases, autowiring can save you time, but it does not really take that much extra effort to define your
wiring explicitly, and you benefit from explicit semantics and full flexibility on property naming and on how many
instances of the same type you manage. For any nontrivial application, steer clear of autowiring at all costs.

Setting Bean Inheritance

Spring allows you to provide a <bean> definition that inherits its property settings
from another bean in the same ApplicationContext.You can override the values of any properties on the child bean
as required, which allows you to have full control, but the parent bean can provide each of your beans with a base
configuration.


<pre name="code" class="html">Listing 3-78. Configuring Bean Inheritance
<?xml version="1.0" encoding="UTF-8"?>
<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
http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="inheritParent" class="com.apress.prospring4.ch3.xml.SimpleBean"
		p:name="Chris Schaefer" p:age="32" />
	<bean id="inheritChild" class="com.apress.prospring4.ch3.xml.SimpleBean"
		parent="inheritParent" p:age="33" />
</beans>



Child beans inherit both constructor arguments and property values from the parent beans

If you are declaring a lot of beans of the same value with
shared property values, avoid the temptation to use copy and paste to share the values; instead, set up an inheritance
hierarchy in your configuration.
Think of bean inheritance
as more like a templating feature than an inheritance feature.

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场