这一篇Blog主要记录一下Spring中一个Bean中对另一个Bean的引用。可以有手动装配和自动装配两种方式。这里还是用例子来说明:
先看一下文件结构图:
其中接口EmployeeService继承Dao,类EmployeeServiceBean继承DaoSupport,并且DaoSupport和EmployeeServiceBean分别实现Dao和EmployeeService。详细如下:
Dao接口:
package beans.service.base;
public interface Dao<T> {
public void save();
public void update();
}
DaoSupport类:package beans.service.base;
public class DaoSupport<T> implements Dao<T> {
@Override
public void save() {
System.out.println("====save=====");
}
@Override
public void update() {
System.out.println("=====update=====");
}
}
EmployeeService接口:
package beans.service.employee;
import beans.entity.Employee;
import beans.service.base.Dao;
public interface EmployeeService extends Dao<Employee> {
}
EmployeeServiceBean类:package beans.service.employee;
import beans.entity.Employee;
import beans.service.base.DaoSupport;
public class EmployeeServiceBean extends DaoSupport<Employee> implements EmployeeService {
}
最后,在EmployeeAction类中添加一个main方法测试。该类中有对EmployeeService的引用。
EmployeeAction.java :
package beans.web.action;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import beans.service.employee.EmployeeService;
public class EmployeeAction {
private EmployeeService employeeService;
public void setEmployeeService(EmployeeService employeeService) {
this.employeeService = employeeService;
}
// public EmployeeAction(){
// System.out.println("-0-0-0-0-0-0-");
// }
public void add(){
employeeService.save();
}
public void update(){
employeeService.update();
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
EmployeeAction ea = (EmployeeAction)context.getBean("employeeAction");
// EmployeeAction ea1 = (EmployeeAction)context.getBean("employeeAction");
ea.add(); //希望最后调用的是Dao中的save方法
// ea1.update();
}
}
使用Spring容器来管理Beans,当然要配置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-2.5.xsd">
<bean id="es" class="beans.service.employee.EmployeeServiceBean">
</bean>
<bean id="employeeAction" class="beans.web.action.EmployeeAction">
<property name="employeeService" ref="es" />
</bean>
</beans>
OK,根据前面前篇Blog:[Spring]初识之第一个Spring小实例的介绍,这样配置当然没有问题。通过在employeeService这个bean中用ref属性引用es这个bean,这也就是最开始说的引用中的手动装配方式。
另外一种方式就是自动装配,自动装配有xml-based和annotation-based两种方式。
1、基于xml方式的自动装配很简单,只是不需要了id=”employeeService“的<bean>的properties子元素,而加上一个autowire属性,如:
<bean id="employeeAction" class="beans.web.action.EmployeeAction"
autowire="byType"></bean>
autowire的属性值有autodetect,byName,byType,constructor,no等,一般常用byName,和byType属性值。比如说在这里因为EmployeeServiceBean类的bean-id是es和EmployeeAction类中的setEmployeeService()方法的employeeService不能对应,所以按照byName就会产生一个空指针异常,而应该用byType,根据bean-id为es的class属性值去和EmployeeAction中对应类型的属性值比对,然后装配。
2、基于annotation方式的自动装配:
首先要修改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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- <bean id="es" class="beans.service.employee.EmployeeServiceBean">
</bean>
<bean id="employeeAction" class="beans.web.action.EmployeeAction"
autowire="byType"></bean> 推荐用属性引用注入的方法 -->
<!-- 设置组件扫面的基包 -->
<context:component-scan base-package="beans" />
<!-- 启用基于annotation的Spring管理Bean组件配置 -->
<context:annotation-config />
</beans>
注意到文件头中加了三个和context有关的东西。还有两个标签,<context:component-scan base-package="beans">和<context:annotation-config>,前者是设置扫描哪个包下的注解,后者是启用注解配置。
理论上来说,所有的类都是JavaBean,而Spring把所有的JavaBean都当做 一个组件。基于annotation的Spring应用就是用注解来标注类,从而把它交给Spring容器来管理,当然还有其他作用的注解。这里我们先把EmployeeServiceBean,DaoSupport和EmployeeAction加上注解:
@Repository
public class DaoSupport<T> implements Dao<T> { ... }
@Service(value="esb")//或者@Service("esb")
public class EmployeeServiceBean extends DaoSupport<Employee> implements EmployeeService { ...}
@Controller
public class EmployeeAction { ... }
为了在EmployeeAction中自动装配EmployeeService,需要在employeeService属性头像添加Autowire注解:
@Autowired
@Qualifier(value="esb")//或者@Qualifier("esb")
private EmployeeService employeeService;
这样配置就完成了引用的自动装配,但有几点要提及:
(1)用来标注组件的常用注解有四个:
|--->@Repository:用来标注Dao组件,可以不标注;
|--->@Service:用来标注业务类;
|--->@Controller:用来标注控制层类;
|--->@Component:这个可以用来标注所有组件,比如上面三个类可以都用它来标注。
(2)
a.给字段employeeService通过@Autowire注解标注,可以完成自动装配。需要注意的是@Autowire默认是按类型装配,若按类型装配失败就会引起一个BeanCreatingException;若要按照名字装配,需要加@Qualifier标注,value值是引用bean的名字。
b.给字段employeeService通过@Resource注解标注,也可以完成自动装配任务。区别于@Autowire的是,@Resource是按bean名字去装配的,按名字装配失败之后,会继续按类型住匹配。但是如@Resource(name="employeeServiceBean"),就会强制按照名字去匹配,失败后会直接引起异常而不会继续按类型匹配。 此外,@Resource是根据反射机制匹配的字段,所以用来标注Field的时候,并不需要为其提供setter。
OK,Spring IoC的引用字段自动装载的学习笔记到此结束。当然,学习的时候不能保证都是理解的正确的,而且大多也是知其然不知其所以然,所以,我会随时纠正和修改其中的一些谬误。如您屈尊来阅,发现其中的错误请不吝指出,当然,为了我的那可怜的自尊心和自信心,请和气交流,*^_^*