使用xml方式实现自动检测和依赖注入需要进行繁琐的xml配置,主要包括两个部分:
(1)使用<bean>...</bean>进行bean的声明;
(2)使用<property>...</property>或者<constructor-arg>...</constructor-arg>进行setter或者构造器的依赖注入
当bean数量比较少时,xml配置比较简单,但是当bean数量非常多,bean和bean之间的依赖也非常复杂,这时候再使用xml配置就会非常繁琐,维护起来也相当复杂,使用注解就相对要简单一些。
还是针对以上两个问题:
(1)Spring框架提供了bean的自动检测来解决bean的声明问题;
(2)Spring框架提供了自动装配功能来解决属性的依赖注入;
1、bean的自动检测
Spring框架提供了以下五种特殊注解来标注类。
@Component -- Spring框架通用的注解,一般用来标注不好归类的类。
@Controller -- 专用于Spring MVC的控制器注解
@Service -- 标识该类为服务
@Repository -- 标识将该类定义为数据仓库
被@Component注解标注的自定义注解
当某一个类被以上注解所标注,并且在Spring的xml文件中做一些配置(具体的配置稍后会提到),Spring框架就会自动将该类识别为一个bean并将其注册到容器中。下面这个例子就是将OracleDaoImpl用@Repository标注为数据仓库,当框架启动时,就会将该类当作一个bean注册到容器中。
package com.springframework.ioc; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; @Repository public class OracleDaoImpl implements MyDao{ private String name; public void setName(String name){ this.name = name; } public String getName(){ return name; } @Override public void addUser(){ System.out.println("this is " + name + " add user..."); } }
可以看到以上OracleDaoImpl类是MyDao的一个子类,MyDao类有时不止有一个实现类,除了OracleDaoImpl之外还有一个MySqlDaoImpl实现类,同样也将这个类用@Repository标注。如下:
package com.springframework.ioc; import java.util.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; @Repository public class MysqlDaoImpl implements MyDao{ private String name; private int id; public void setName(String name){ this.name = name; } public String getName(){ return name; } @Override public void addUser(){ System.out.println("this is " + name + " id is " + id + " add user..."); } }
这个时候就会有一个问题,我该如何区分这两个bean呢?在xml配置中,我们会根据bean的id来区分,同样在也可使用注解加bean id来进行区分,修改如下:
package com.springframework.ioc; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; @Repository("OracleDao") public class OracleDaoImpl implements MyDao{ private String name; public void setName(String name){ this.name = name; } public String getName(){ return name; } @Override public void addUser(){ System.out.println("this is " + name + " add user..."); } }
将OracleDaoImpl类声明为id为“OracleDao”的bean。
package com.springframework.ioc; import java.util.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; @Repository("MysqlDao") public class MysqlDaoImpl implements MyDao{ private String name; private int id; public void setName(String name){ this.name = name; } public String getName(){ return name; } public MysqlDaoImpl(){ } public MysqlDaoImpl(String name, int id){ this.name = name; this.id = id; } @Override public void addUser(){ System.out.println("this is " + name + " id is " + id + " add user..."); } }
将MysqlDaoImpl声明为id为“MysqlDao”的bean。
这个时候就可以通过bean的id来对bean进行区分,也就为后面的自动装配做好铺垫。
前面说到,要使用bean的自动检测功能,需要对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" default-lazy-init="true"> <!--对所有bean进行延迟初始化--> <!-- 自动扫描bean 自动装配bean --> <context:component-scan base-package="com.springframework.ioc"/> </beans>
使用
<context:component-scan base-package="com.springframework.ioc"/>
来指出需要自动检测的包即可。
二、自动装配
在自动检测完成bean,将bean注册到容器中后,接下来的任务就是自动装配了。
Spring框架提供了注解@Autowired标注属性、setter方法或者是构造器来解决对象的依赖问题,举例,要在service层调用dao层,则如下所示:
package com.springframework.ioc; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service("myService2") public class MyService2{ @Autowired @Qualifier("OracleDao") private MyDao myDao; public MyDao getMyDao() { return myDao; } }
可以看到,在service层有一个myDao属性,使用@Autowired和@Qualifier来自动装配bean,其中:
使用@Autowired注解表明是自动装配,使用@Qualifier注解来指出要装配的bean的id,以便匹配。
另外需要说明的是:使用的这些注解都是Spring框架提供的,这样代码就会和Spring框架耦合比较大,可以使用基于Java的注解@Inject 和@Named() 分别对应@Autowired和@Qualified()