先来看一个setter注入:(注入的是其他bean)
//写bean标签 配置id class
//添加property子标签 配置name ref(如果注入的是其他bean就配置name和ref)
<bean id="accountService" class="com.wiley.beginningspring.ch2.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
再来看一个setter注入(注入的是纯粹值)
<bean id="account1" class="com.wiley.beginningspring.ch2.Account">
<property name="id" value="1"/>
<property name="ownerName" value="John"/>
<property name="balance" value="10.0"/>
<property name="locked" value="false"/>
</bean>
再再看一个setter注入(注入的还是纯粹值)
<bean id="account2" class="com.wiley.beginningspring.ch2.Account">
<property name="id" value="2"/>
<property name="ownerName" value="Mary"/>
<property name="balance" value="20.0"/>
<property name="locked" value="false"/>
</bean>
发现了什么没有?:
//如果是注入纯粹值 就配置name和value
再来看一个setter注入:(注入的是一个map的bean集合)
//如果是map类型的属性
//property用双标签
//只要配置一个name
//添加map子标签
//添加entry单标签
//配置key 和 value-ref
<bean id="accountDao" class="com.wiley.beginningspring.ch2.AccountDaoInMemoryImpl">
<property name="accountsMap">
<map>
<entry key="1" value-ref="account1"/>
<entry key="1" value-ref="account2"/>
</map>
</property>
</bean>
恭喜你,你看完了所有类型的setter注入!!!!!!
//定义一个service实现类
public class AccountServiceImpl implements AccountService{
//定义一个AccountDao类型的属性 accountDao;
private AccountDao accountDao;
//定义该类的一个构造函数方法 接受一个AccountDao类型的参数accountDao
public AccountServiceImpl(AccountDao accountDao){
//将传入的参数设置给类的accountDao属性
this.accountDao = accountDao;
}
}
下面看一个构造函数注入:!!!
//xml文件头声明
//xml标签配置version encoding
<?xml version="" encoding=""?>
//beans标签 配置xmlns xmlns:xsi xsi:schemaLocation
<beans xmlns="" xmlns:xsi="" xsi:schemaLocation="">
//看这里!!!!
<bean id="accountService" class="com.wiley.beginningspring.ch2.AccountServiceImpl">
<constructor-arg ref="accountDao"/>
</bean>
<bean id="accountDao" class="com.wiley.beginnignspring.ch2.AccountDaoInMemoryImpl">
//这里不用管
</bean>
</beans>
下面来实例化Spring容器 (盛放bean的瓶子)
将XMLBean定义文件作为参数来实例化spring容器
public class Main{
public static void main(String[] args){
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("/com/wiley/beginningspring/ch2/ch2-beans.xml");
}
}
从spring容器中访问accoutnService Bean
(既然盛放了bean,需要哪个bean就取(get)哪个)
AccountService accountService = applicationContext.getBean(
"accountService",AccountService.class);
System.out.println("Before money transfer");
//之前对accountDao配置了map所以这里可以取到两个account(1和2)
System.out.println("Account 1 balance:" +
accountService.getAccount(1).getBalance());
System.out.println("Account 2 balance:" +
accountService.getAccount(2).getBalance());
accountService.transferMoney(1,2,5.0);
System.out.pringln("After money transfer");
System.out.println("Account 1 balance:" +
accountService.getAccount(1).getBalance());
System.out.println("Account 2 balance :" +
accountService.getAccount(2).getBalance());
看下面就会知道构造注入的实现原理!!!!!
//创建Foo类
public class Foo{
//创建Bar类型的bar属性
private Bar bar;
//创建Baz类型的baz属性
private Baz baz;
//创建类的第一个构造函数(接受两个参数先后分别为Bar类型 和 Baz类型)
public Foo(Bar bar,Baz baz){
//将参数分别设置给类的bar属性和baz属性
this.bar = bar;
this.baz = baz;
}
//创建类的第二个构造函数(接受两个参数先后分别为Baz类型 和 Bar类型)
public Foo(Baz baz,Bar bar){
//将参数赋值给类的属性
this.baz = baz;
this.bar = bar;
}
//两个构造方法的区别是参数个数类型都相同但是先后顺序不同
}
创建 Bar类
public class Bar{
}
创建 Baz类
public class Baz{
}
<bean id="foo" class="com.wiley.beginningspring.ch2.Foo">
//通过构造函数的方法创建bean实例
<constructor-arg ref="bar" />
<constructor-arg ref="baz" />
//且构造函数的参数类型分别为Bar类型 和 Baz类型
</bean>
<bean id="bar" class="com.wiley.beginningspring.ch2.Bar"/>
<bean id="baz" class="com.wiley.beginningspring.ch2.Baz"/>
问题: spring容器无法实例化fooBean
解决方法:给构造方法函数的参数加上索引 以表明先后顺序
//id的含义是该beand的标识(唯一的那种名字)
//class表明该实例bean的所属的类
//下面指明创建一个bean实例
<bean id="foo" class="com.wiley.beginningspring.ch2.Foo">
<constructor-arg ref="bar" index="0"/>
<constructor-arg ref="baz" index="1"/>
//这两行代码表明通过类的构造函数来创建bean实例且
//第一个参数是引用的名为bar的bean实例
//第二个参数是引用的名为baz的bean实例
</bean>
//一个bean就是一个类实例
//只不过这个实例是spring管理的
<bean id="bar" class="com.wiley.beginningspring.ch2.Bar"/>
//读到的信息: bean实例 名为bar 所属类是Bar
<bean id="baz" class="com.wiley.beginningspring.ch2.Baz"/>
// bean 实例 名为baz 所属类是Baz
看下面就知道开发中用的是两种方式的联合!!!!
//创建类Foo
public clas Foo {
//定义Bar类型的属性 bar
private Bar bar;
//定义Baz类型的属性 baz
private Baz baz;
//定义类的构造函数 参数为Bar类型的bar
public Foo(Bar bar){
//将参数设置给bar属性
this.bar = bar;
}
//定义属性baz的setter方法
public void setBaz(Baz baz){
this.baz = baz;
}
}
//定义Baz类
public Baz{
}
//定义Bar类
public Bar{
}
<bean id="foo" class="com.wiley.beginningspring.ch2.Foo">
//调用构造函数创建实例
<constructor-arg ref="bar"/>
//调用属性baz的方法 传入名为baz的bean作为参数
<property name="baz" ref="baz"/>
</bean>
<bean id="baz" class="com.wiley.beginningspring.ch2.Baz"/>
<bean id="bar" class="com.wiley.beginningspring.ch2.Bar"/>