60 seconds to Spring (3)

60 sec to Spring [TOC]

Bean Tutorial 3 - Setter-Based and Construction-Based Dependency Injection

Inversion of Control/Dependency Injection exists in two major variants:

  • Setter-based dependency injection is realized by calling setters on your beans after invoking a no-argument constructor to instantiate your bean. Beans defined in the BeanFactory that use setter-based dependency injection are true JavaBeans. Spring generally advocates usage of setter-based dependency injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional.

  • Constructor-based dependency injection is realized by invoking a constructor with a number of arguments, each representing a collaborator or property.


Step 1: We will need two dummy classes for our tutorial, AnotherBean.java and YetAnotherBean.java.

org/jarchitect/spring/tutorial3/AnotherBean.java

package org.jarchitect.spring.tutorial3; public class AnotherBean { public AnotherBean() { System.out.println("Construct AnotherBean"); } }

org/jarchitect/spring/tutorial3/YetAnotherBean.java

package org.jarchitect.spring.tutorial3; public class YetAnotherBean {  public YetAnotherBean() {  System.out.println("Construct YetAnotherBean"); } }

Step 2: We will create a ConstructorExampleBean and a SetterExampleBean.

org/jarchitect/spring/tutorial3/ConstructorExampleBean.java

package org.jarchitect.spring.tutorial3; public class ConstructorExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public ConstructorExampleBean( AnotherBean anotherExampleBean, YetAnotherBean yetAnotherBean, int i) { this.beanOne = anotherExampleBean; this.beanTwo = yetAnotherBean; this.i = i; System.out.println("Construction Done!!!"); } public ConstructorExampleBean() { System.out.println("Default Constructor : Should not be call!!!"); } }

org/jarchitect/spring/tutorial3/SetterExampleBean.java

package org.jarchitect.spring.tutorial3; public class SetterExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public SetterExampleBean() { System.out.println("Default Constructor"); } public void setBeanOne(AnotherBean bean) { this.beanOne = bean; System.out.println("Set beanOne"); } public void setBeanTwo(YetAnotherBean bean) { this.beanTwo = bean; System.out.println("Set beanTwo"); } public void setIntegerProperty(int i) { this.i = i; System.out.println("Set i"); } }

Step 3: Specify the HelloBean class in the bean.xml

bean.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans>  <description>jarchitect Spring Tutorial 3</description> <bean id="setterBean" class="org.jarchitect.spring.tutorial3.SetterExampleBean"> <description>Setter-based Dependency Injection.</description> <property name="beanOne"><ref bean="anotherExampleBean"/></property> <property name="beanTwo"><ref bean="yetAnotherBean"/></property> <property name="integerProperty"><value>1</value></property> </bean> <bean id="constructorBean" class="org.jarchitect.spring.tutorial3.ConstructorExampleBean"> <description>Constructor Dependency Injection</description> <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg> <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg> <constructor-arg index="2"><value>1</value></constructor-arg> </bean> <bean id="anotherExampleBean" class="org.jarchitect.spring.tutorial3.AnotherBean"/> <bean id="yetAnotherBean" class="org.jarchitect.spring.tutorial3.YetAnotherBean"/> </beans>

Step 4: reate a Main.java in src

org/jarchitect/spring/tutorial3/Main.java

package org.jarchitect.spring.tutorial3; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.springframework.beans.factory.xml.XmlBeanFactory; public class Main { public static void main(String[] args) { try { //Read the configuration file InputStream is = new FileInputStream("bean.xml"); XmlBeanFactory factory = new XmlBeanFactory(is); //Instantiate SetterExampleBean SetterExampleBean setterBean = (SetterExampleBean) factory.getBean("setterBean"); //Instantiate ConstructorExampleBean ConstructorExampleBean constructorBean = (ConstructorExampleBean) factory.getBean("constructorBean"); } catch (FileNotFoundException e) { e.printStackTrace(); } } }

Step 5: Use an ANT script to build and execute the Main class. Just run ant from the command prompt will do the trick.

Below are the output from ANT.

C:/60sec2Spring/SpringTutorial3>ant Buildfile: build.xml build: [javac] Compiling 5 source files to C:/60sec2Spring/SpringTutorial3/bin run: [java] Jun 1, 2004 12:36:51 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions [java] INFO: Loading XML bean definitions from (no description) [java] Jun 1, 2004 12:36:51 PM org.springframework.beans.factory.support.AbstractBeanFactory getBean [java] INFO: Creating shared instance of singleton bean 'setterBean' [java] Default Constructor [java] Construct AnotherBean [java] Jun 1, 2004 12:36:51 PM org.springframework.beans.factory.support.AbstractBeanFactory getBean [java] INFO: Creating shared instance of singleton bean 'anotherExampleBean' [java] Construct YetAnotherBean [java] Set beanOne [java] Set beanTwo [java] Jun 1, 2004 12:36:51 PM org.springframework.beans.factory.support.AbstractBeanFactory getBean [java] INFO: Creating shared instance of singleton bean 'yetAnotherBean' [java] Set i [java] Jun 1, 2004 12:36:51 PM org.springframework.beans.factory.support.AbstractBeanFactory getBean [java] INFO: Creating shared instance of singleton bean 'constructorBean' [java] Construction Done!!! [java] Jun 1, 2004 12:36:51 PM org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory autowireConstructor [java] INFO: Bean 'constructorBean' instantiated via constructor [public org.jarchitect.spring.tutorial3. ConstructorExampleBean(org.jarchitect.spring.tutorial3.AnotherBean,org.jarchitect.spring.tutorial3.YetAnotherBean,int)] BUILD SUCCESSFUL Total time: 2 seconds

Overtime

From bean.xml

...... <bean id="constructorBean" class="org.jarchitect.spring.tutorial3.ConstructorExampleBean"> <description>Constructor Dependency Injection</description> <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg> <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg> <constructor-arg index="2"><value>1</value></constructor-arg> </bean> ......

Notice the index="2", try removing it and run ANT again. You will have the following error.

....... [java] INFO: Creating shared instance of singleton bean 'constructorBean' [java] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'constructorBean' defined in (no description): 3 constructor arguments specified but no matching constructor found in bean 'constructorBean'(hint: specify index arguments for simple parameters to avoid type ambiguities) [java] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory. autowireConstructor(AbstractAutowireCapableBeanFactory.java:287) [java] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory. createBean(AbstractAutowireCapableBeanFactory.java:181) [java] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:159) [java] at org.jarchitect.spring.tutorial3.Main.main(Unknown Source) [java] Exception in thread "main" [java] Java Result: 1 BUILD SUCCESSFUL Total time: 1 second

Reason: The argument is an int, but BeanFactory take it as a String, so the mapping isn't obvious to the matching algorithm. In case of primitives, it's recommended to specify the argument index explicitly.

More Reason: For example, constructors MyClass(bool flag, String toto, int moo, float cow). There is no way for the BeanFactory to tell which is which from the string representations of each.

Next, try swapping

 <constructor-arg index="2"><value>1</value></constructor-arg>  <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg>  <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg>

and run ANT.

Done.

[TOC]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值