4.构造器方式注入
- step1. 添加构造器方法.
step2. 配置constructor-arg 元素
- index属性:指定参数的下标
- ref属性:指被传进来的bean的ID
类A
package ioc;
public class A {
private B b;
public A(B b) {
System.out.println("A(B)");
this.b = b;
}
public A() {
System.out.println("A()");
}
public void execute() {
System.out.println("execute()");
b.f1();
}
}
- 类B
package ioc;
public class B {
public B() {
System.out.println("B()");
}
public void f1() {
System.out.println("B's f1()");
}
}
- Test
@Test
//测试构造器方式注入
public void test1() {
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc.xml");
A a1 = ac.getBean("a1",A.class);
a1.execute();
}
- xml文件
<!--
constructor-arg元素:配置构造器方式注入
index属性:指定参数的下标(从0开始)
ref属性:指被传进来的bean的ID
-->
<bean id="b1" class="ioc.B"></bean>
<bean id="a1" class="ioc.A">
<constructor-arg index="0" ref="b1">
</constructor-arg>
</bean>
5.自动装配
- 自动装配,指的是spring容器依据某种规则,自动建立对象之间的依赖关系.
注意:
- 默认情况下,容器不会自动装配.
- 可以通过指定autowire(自动装配)属性,进行自动装配.容器仍然需要通过调用set/构造器来完成依赖关系的建立.
- 自动装配优先使用byName.
类restaurant
package ioc;
public class Restaurant {
private Waiter wt;
public Restaurant() {
System.out.println("Restaurant()");
}
public void setWt(Waiter wt) {
System.out.println("setWt()");
this.wt = wt;
}
@Override
public String toString() {
return "Restaurant [wt=" + wt + "]";
}
}
- 类writer
package ioc;
public class Waiter {
public Waiter() {
System.out.println("Waiter()");
}
}
- xml文件
<bean id="wt1" class="ioc.Waiter"></bean>
<!--
autowire属性:表示让容器自动装配,如果值为
注意:
byName:
byName:容器依据属性名查找对应的bean,然后调用对应的set方法来完成注入
1.如果找不到对应的bean,则会注入null.
2.不可能找到多个符合条件的bean.
byType:
容器依据属性类型查找对应bean,然后调用对应的set方法来完城注入.
注意:
1.找不到仍然注入空值
2.有可能找到多个符合条件的bean会出错.
constructor:
与byType类似,不同的是调用对应的构造器来注入.
-->
<bean id="rest" class="ioc.Restaurant" autowire="byType"></bean>
- @test
@Test
//测试自动装配
public void test2() {
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc.xml");
Restaurant rest = ac.getBean("rest",Restaurant.class);
System.out.println(rest);
}
6.注入基本类型的值
- 使用value属性
7.注入集合类型的值
List Set Map Properties
测试类
package value;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class ValueBean {
private String name;
private int age;
private List<String> city;
private Set<String> interest;
private Map<String, Integer> source;
private Properties db;
public void setDb(Properties db) {
this.db = db;
}
public void setSource(Map<String, Integer> source) {
this.source = source;
}
public void setInterest(Set<String> interest) {
this.interest = interest;
}
public void setCity(List<String> city) {
this.city = city;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public ValueBean() {
System.out.println("ValueBean()");
}
@Override
public String toString() {
return "ValueBean [name=" + name + ", age=" + age + ","
+ " city=" + city + ", interest=" + interest + ", source="
+ source + ", db=" + db + "]";
}
}
- xml文件
<bean id="vb1" class="value.ValueBean">
<property name="name" value="张三"></property>
<property name="age" value="23"></property>
<property name="city">
<list>
<value>北京</value>
<value>上海</value>
<value>广州</value>
</list>
</property>
<property name="interest">
<set>
<value>唱歌</value>
<value>跳舞</value>
<value>学习</value>
</set>
</property>
<property name="source">
<map>
<entry key="语文" value="98"></entry>
<entry key="数学" value="99"></entry>
<entry key="英语" value="88"></entry>
</map>
</property>
<property name="db">
<props>
<prop key="username">scott</prop>
<prop key="password">tiger</prop>
<prop key="drivar">oracle.jdbc.OracleDriver</prop>
<prop key="url">jdbc:oracle:thin:@192.168.56.101:1521:orcl</prop>
</props>
</property>
</bean>
- @Test
@Test
//测试基本类型值得注入
public void test3() {
ApplicationContext ac = new ClassPathXmlApplicationContext("value.xml");
ValueBean vb = ac.getBean("vb1",ValueBean.class);
System.out.println(vb);
}
- 输出
ValueBean()
ValueBean [name=张三, age=23, city=[北京, 上海, 广州], interest=[唱歌, 跳舞, 学习], source={语文=98, 数学=99, 英语=88}, db={url=jdbc:oracle:thin:@192.168.56.101:1521:orcl, password=tiger, drivar=oracle.jdbc.OracleDriver, username=scott}]
8.引用方式注入集合的值
- 示例代码
<!-- 将集合类型的值配置成一个bean -->
<util:list id="cityBean">
<value>丽江</value>
<value>桂林</value>
<value>云南</value>
</util:list>
<util:set id="interestBean">
<value>书法</value>
<value>绘画</value>
<value>拳击</value>
</util:set>
<util:map id="sourceBean">
<entry key="政治" value="99"></entry>
<entry key="历史" value="78"></entry>
<entry key="地理" value="79"></entry>
</util:map>
<util:properties id="dbBean">
<prop key="username">hr</prop>
<prop key="password">h1</prop>
</util:properties>
<!-- 引用的方法注入集合类型的值 -->
<bean id="vb2" class="value.ValueBean">
<property name="city" ref="cityBean"></property>
<property name="interest" ref="interestBean"></property>
<property name="source" ref="sourceBean"></property>
<property name="db" ref="dbBean"></property>
<property name="name" value="李四"></property>
<property name="age" value="26"></property>
</bean>
9.读取properties文件的内容
- 示例代码
<!-- 读取properties问文件的内容
classpath:表示按照类路径来搜索.
spring容器会依据这个路径找到对应的配置文件,然后 读取内容到properties对象
-->
<util:properties id="config" location="classpath:config.properties"/>
10.使用spring表达式
- xml文件
<!-- spring表达式用来读取其他bean的属性值 -->
<bean id="sp1" class="value.SpelBean">
<property name="name" value="#{vb1.name}"/>
<property name="city" value="#{vb1.city[0]}"/>
<property name="score" value="#{vb1.source['语文']}"/>
<property name="pageSize" value="#{config.pagesize}"></property>
</bean>
vb1是bean的id,name是属性名
使用注解简化配置
1.组件扫描
- 概述:指的是Spring容器在启动之后,会扫描指定的包及其子包下面的所有的类,如果该类前面有特定的注解(比如@Component),则Spring容器会将其这个类纳入容器进行管理.
2.如何进行组件扫描
- step1:添加注解
package annotation;
import org.springframework.stereotype.Component;
/*
* 注解:Component
* sb1 是bean的id,它的缺省值是类名首字母小写之后的类名.
*/
@Component("sb1")
//组件
public class SomeBean {
public SomeBean() {
System.out.println("SomeBean()");
}
}
注解标记
- @Component(Spring框架提供) 通用注解
- @Repository 持久化层组件注解
- @Service 业务层组件注解
- @Controller 控制层组件注解
作用是等价的,可用通用,只不过有语义上的差异
step2:在配置文件当中添加组件扫描的配置
<!-- 配置组件扫描 -->
<!--
base-package属性:指定要扫描的包名,spring容器会扫描该包及其子包下面的所有的类,如果前面有特定的注解
(比如:@Component),则spring容器会将其纳入容器进行管理(相当于配置了一个bean元素)
-->
<context:component-scan base-package="annotation"/>
3.作用标记
- @Scope()
- @Component(“sb1”)
- @Lazy(true)
- @PostConstruct
- @PreDestroy
package annotation;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/*
* 注解:Component
* sb1是bean的id,它的缺省值是类名首字母小写之后的类名.
*/
//@Scope("prototype")//指定作用域
@Component("sb1") //通用注解
@Scope("singleton") //单例模式.默认的
@Lazy(true) //表示延迟加载
//组件
public class SomeBean {
//表示初始化注解
@PostConstruct
public void init() {
System.out.println("init()");
}
//表示销毁之前,需要把作用改成单例,因为原型不起作用
@PreDestroy
public void destroy() {
System.out.println("destroy");
}
public SomeBean() {
System.out.println("SomeBean()");
}
}
- @Test
@Test
//测试注解
public void test8() {
ApplicationContext ac = new ClassPathXmlApplicationContext("annotation.xml");
SomeBean sb1 = ac.getBean("sb1",SomeBean.class);
System.out.println(sb1);
}
@Test
//测试作用域
public void test9() {
ApplicationContext ac = new ClassPathXmlApplicationContext("annotation.xml");
SomeBean sb1 = ac.getBean("sb1",SomeBean.class);
SomeBean sb2 = ac.getBean("sb1",SomeBean.class);
System.out.println(sb1 == sb2);
}
@Test
//测试生命周期相关的方法
public void test10() {
AbstractApplicationContext ac = new ClassPathXmlApplicationContext("annotation.xml");
SomeBean sb1 = ac.getBean("sb1",SomeBean.class);
ac.close();
}
@Test
//测试延迟加载
public void test11() {
ApplicationContext ac = new ClassPathXmlApplicationContext("annotation.xml");
}