依赖注入分为手工装配和自动装配,自动装配会产生大量的我们不需要的东西,所以这里我只讲手工装配注入依赖对象。
手工装配注入依赖对象,又分为两种,一种是我们在上一篇文章中所着重提到的通过构造方法注入和通过setter方法注入。这种方式在大型项目开发中会产生一个问题,那就是配置文件非常的臃肿,不便于管理,下面我们来讲第二种:在Java代码中使用注解的方式注入。
先来看看项目结构(假设操作的是Role对象)!
数据访问层接口IRoleDao.java:
/**
* 数据访问层接口
* @author Liao
*/
public interface IRoleDao {
/**
* 测试方法
*/
public void test();
}
数据访问层接口实现类RoleDaoImpl.java:
/**
* 数据访问层接口实现类
* @author Liao
*/
public class RoleDaoImpl implements IRoleDao{
@Override
public void test() {
System.out.println("您调用了测试方法");
}
}
业务逻辑层接口IRoleService.java:
/**
* 业务逻辑层接口
* @author Liao
*/
public interface IRoleService {
/**
* 测试方法
*/
public void test();
}
业务逻辑层接口实现类:
/**
* 业务逻辑层接口实现类
* @author Liao
*/
public class RoleServiceImpl implements IRoleService{
@Resource
private IRoleDao roleDao;
@Override
public void test() {
/*通过数据访问层dao调用方法*/
roleDao.test();
}
}
Spring的配置文件我们也要有所改变:
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 注解的声明不要漏掉了 -->
<context:annotation-config />
<!-- 注:这个bean是dao的id,因为此时我们是采用注解的方式注入,注解非常灵活,如果名称不对会通过类型进行匹配,所以这个id可以随便取值,但是不提倡,还是建议和变量名称相同 -->
<bean id="roleDao" class="com.lixue.dao.impl.RoleDaoImpl"></bean>
<bean id="roleServiceImpl" class="com.lixue.service.impl.RoleServiceImpl"></bean>
</beans>
注:在Spring的配置文件中我们要做的就是声明bean,把它们纳入Spring容器进行管理,然后在Java代码中使用注解来注入这些bean。
在Service实现类中我们看到了一个@Resource注解,其实还有另外一个注解可以供我们选择,那就是@Autowired,使用这两个注解要注意的问题:
1.必须有无参构造函数。
2.@Resource是JDK自带的注解,而@Autowired是Spring提供的注解,@Autowired默认是按类型装配,@Resource默认是按名称进行装配,当找不到与名称匹配的bean才会按类型装配,这就涉及到一个性能问题,因为@Resource是根据名称进行匹配,那么我们只要在配置文件中配置和变量相同的名称就可以非常迅速的定位到相应的bean,如果是按类型找的话速度就很慢,所以使用@Resource更好。
3.因为这两个注解都可以按类型进行匹配,这就有一个好处,我们在配置文件中定义要被注入的bean时,它的id可以随便取,因为可以通过类型进行匹配。
4.这两个注解可以作用在变量上,也可以作用在setter方法上(据说作用在变量上之后会使变量自动成为public类型,比较不安全,提倡作用在setter方法上,但是这个我没测试过,有知道的还请多多指教)。
5.@Resource可以指定名称@Resource(name="XXX"),如果没有指定名称那么先按默认的名称默认的名称(变量名称)进行寻找,找不到再按类型寻找,但是有一点千万要注意,一旦指定了name属性,就不会再按类型进行匹配了,也就是说如果你要指定name属性,那么一定要和在配置文件中的bean的id一致,否则会报错。
6.其实@Autowired也可以按照名称进行匹配,但是比较麻烦,要和另外一个注解结合使用:@Autowired @Qualifier("XXX")
7.@Autowired注解是按类型匹配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。
8.不要忘记加上@Resource注解的jar包:common-annotations.jar
作用在setter方法上:
public class RoleServiceImpl implements IRoleService{
private IRoleDao roleDao;
@Resource
public void setRoleDao(IRoleDao roleDao) {
this.roleDao = roleDao;
}
@Override
public void test() {
/*通过数据访问层dao调用方法*/
roleDao.test();
}
}
测试类:
public class RoleTest {
public static void main(String[] args) {
/*初始化Spring容器*/
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"role-beans.xml"});
/*ctx.getBean("RoleServiceImpl")获取Bean*/
//System.out.println(ctx.getBean("roleServiceImpl"));
IRoleService roleService = (IRoleService) ctx.getBean("roleServiceImpl");
roleService.test();
}
}