【一步一步学习spring】spring bean管理(下)
3. 依赖注入
3.1 spring的属性注入(xml方式)
- 构造方法注入
- 属性setter方法注入
3.1.1 构造方法注入
- 通过构造方法注入bean的属性值或依赖的对象,它保证了bean实例在实例化就可以使用
- 构造器注入在
<constructor-arg>
元素中声明属性
<bean id = "user" class="com.ioc.demo4.User">
<constructor-arg name="name" value="xxx"></constructor-arg>
<constructor-arg name="age" value="29"></constructor-arg>
</bean>
3.1.2 set方法注入
- 同过
<property>
设置注入的属性
<bean id="cat" class="com.ioc.demo4.Cat">
<property name="name" value="ccc"></property>
</bean>
<bean id="person" class="com.ioc.demo4.Person">
<property name="name" value="aaa"></property>
<property name="age" value="88"></property>
<property name="cat" ref="cat"></property>
</bean>
3.1.3 c名称空间
- 为了简化XML文件配置
- c:<属性名>="xxx"引入常量值
- c<属性名>-ref="xxx" 引入其他bean对象
引入c包
xmlns:p="http://www.springframework.org/schema/c"
<bean id="user" class="com.ioc.demo4.User" c:name="ooo" c:age="88"></bean>
3.1.4 p名称空间
- 为了简化XML文件配置,spring从2.5开始引入一个新的p名称空间
- p:<属性名>="xxx"引入常量值
- p:<属性名>-ref="xxx" 引入其他bean对象
引入p包
xmlns:p="http://www.springframework.org/schema/p"
<bean id="cat" class="com.ioc.demo4.Cat" p:name="xiaohuang"></bean>
<bean id="person" class="com.ioc.demo4.Person" p:name="aaa" p:age="99" p:cat-ref="cat"></bean>
3.1.5 SpEL注入
- SpEL:spring expression language, spring表达式语言,对依赖注入进行简化
- 语法:#
<bean id="" value="#{表达式}">
<bean id="cat" class="com.ioc.demo4.Cat" p:name="#{'xiaohuang'}"></bean>
<bean id="person" class="com.ioc.demo4.Person" p:name="#{'aaa'}" p:age="#{99}" p:cat="#{cat}"></bean>
当然表达式可以是java语句,可以用其他bean的方法来给目标bean赋值。
比如age是Manger类中管理的。
<bean id="manage" class="com.ioc.demo4.Manager"></bean>
<bean id="cat" class="com.ioc.demo4.Cat" p:name="#{'xiaohuang'}"></bean>
<bean id="person" class="com.ioc.demo4.Person" p:name="#{'aaa'}" p:age="#{manage.getAge('aaa')}" p:cat="#{cat}"></bean>
3.1.6 复杂类型的属性注入
<!-- 复杂类型的bean属性注入 -->
<bean id="collection" class="com.ioc.demo4.CollectionBean">
<!-- 数组 -->
<property name="array">
<array>
<value>xxx</value>
<value>qqq</value>
<value>www</value>
</array>
</property>
<!-- 列表 -->
<property name="list">
<list>
<value>111</value>
<value>222</value>
<value>333</value>
<value>444</value>
</list>
</property>
<!-- 集合 -->
<property name="set">
<set>
<value>xiaohuang</value>
<value>xiaohuang</value>
<value>xiaohong</value>
</set>
</property>
<!-- 字典 -->
<property name="map">
<map>
<entry key="x" value="xxx"></entry>
<entry key="y" value="yyy"></entry>
<entry key="z" value="zzz"></entry>
</map>
</property>
</bean>
3.2 spring的属性注入(注解方式)
3.2.1 使用注解定义Bean
- @Component 描述Spring框架中的Bean
- 除了@Component外,spring提供了3个功能基本和@Component等效的注解,为了区分类功能
- @Repository 用于对Dao实现类进行标注
- @Service 用于对Service实现类进行标注
- @Controller 用于对Controller实现类进行标注
- xml 头修改为:
<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"
xmlns:c="http://www.springframework.org/schema/c"
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">
- xml开启注解扫描,配置包扫描路径
<context:component-scan base-package="com.ioc"></context:component-scan>
- bean
@Component("abean1")
public class Bean1 {
public void sayHello() {
System.out.println("hello");
}
}
- 调用
public void demo1() {
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
Bean1 bean = (Bean1)context.getBean("abean1");
bean.sayHello();
}
3.2.2 使用注解注入属性
- 普通类型属性
- 使用@Value进行自动注入
@Value("aaa")
private String name;
-
对象类型属性
-
使用@Autowired进行自动注入
-
@Autowired默认按照类型进行注入
-
@Autowired注入时可以针对成员变量或者set方法
- 依赖类Bean1Dao
@Repository("bean1dao") public class Bean1Dao { @Value("dao") private String name; @Override public String toString() { return "Bean1Dao [name=" + name + "]"; } }
- 引用类Bean1
@Autowired private Bean1Dao dao;
-
在@Autowired下边添加@Qualifier也可以指定名称。
- 引用类Bean1
@Autowired @Qualifier("bean1dao") private Bean1Dao dao;
-
当然,使用@Resource可以代替上边的这两个注解
- 引用类Bean1
@Resource(name="bean1dao") private Bean1Dao dao;
如果出现没有@Resource注解的情况,需要引入下边的依赖包
<dependency> <groupId>javax.annotation</groupId> <artifactId>jsr250-api</artifactId> <version>1.0</version> </dependency>
-
3.3 spring的其他注解
3.3.1 初始化和销毁方法
Spring初始化bean或销毁bean时,有时需要做一些处理工作,因此spring可以在创建和拆卸bean的时候调用bean的两个生命周期方法。
xml配置的方法时:
<bean id="xxx" class="...Yoo" init-method="init" destory-method="destory" />
注解的方式:
@PostConstruct 初始化
@PreDestroy 销毁(只有单例下有效)
bean中可以添加
@PostConstruct
private void init() {
System.out.println("init......");
}
@PreDestroy
private void destroy() {
System.out.println("destory.......");
}
3.3.2 bean的scope
- 使用注解配置的bean和
<bean>
配置是一样的,默认是singleton - @Scope注解用于指定Bean的作用范围
4. 传统xml配置和注解配置混合使用
- xml方式的优势
- 结构清晰,易于阅读
- 注解方式的优势
- 开发便捷,属性注入方便
故我们应该取其优势使用,使用xml方式来管理bean,使用注解方式做属性注入。
- xml管理bean
<context:annotation-config/>
<bean id="categorydao" class="com.ioc.mix.demo.CategoryDao"/>
<bean id="productdao" class="com.ioc.mix.demo.ProductDao"/>
<bean id="productservice" class="com.ioc.mix.demo.ProductService"/>
可以看到上面的xml中多了一个<context:annotation-config/>
,这个是把属性注入的注解开启。而我们前面用到的<context:component-scan base-package="com.xxx">
是把所有的注解都打开。
- annotation来做属性注入
package com.ioc.mix.demo;
import org.springframework.beans.factory.annotation.Autowired;
public class ProductService {
@Autowired
private CategoryDao categorydao;
@Autowired
private ProductDao productdao;
public void save() {
System.out.println("product service save");
categorydao.save();
productdao.save();
}
}