学科分类
目录
SSM框架

基于Annotation的装配

在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean时,会导致XML配置文件过于臃肿,给后续的维护和升级工作带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。

Spring中定义了一系列的注解,常用的注解如下所示。

● @Component:可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean) ,并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。

● @Repository:用于将数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component 相同。

● @Service:通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component 相同。

● @Constroller:通常作用在控制层(如Spring MVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component 相同。

● @Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。

● @Resource:其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。

● @Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

在上面几个注解中,虽然@Repository、@Service与@Constroller功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository、@Service与@Constroller分别对实现类进行标注。

下面,通过一个案例来演示如何通过这些注解来装配Bean。

(1)在chapter02项目的src目录下,创建一个com.itheima.annotation包,在该包中创建接口UserDao,并在接口中定义一个save()方法,如文件1所示。

文件1 UserDao.java

 1    package com.itheima.annotation;
 2    public interface UserDao {
 3        public void save();
 4    }

(2)在com.itheima.annotation包中,创建UserDao接口的实现类UserDaoImpl,该类需要实现接口中的save()方法,如文件2所示。

文件2 UserDaoImpl.java

 1    package com.itheima.annotation;
 2    import org.springframework.stereotype.Repository;
 3    @Repository("userDao") 
 4    public class UserDaoImpl implements UserDao{
 5       public void save(){
 6          System.out.println("userdao...save...");
 7       }
 8    }

在文件2中,首先使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中<bean id="userDao" class="com.itheima.annotation.UserDaoImpl"/>的编写。然后在save()方法中输出打印一句话,用来验证是否成功调用了该方法。

(3)在com.itheima.annotation包中,创建接口UserService,在接口中同样定义一个save()方法,如文件3所示。

文件3 UserService.java

 1    package com.itheima.annotation;
 2    public interface UserService {
 3        public void save();
 4    }

(4)在com.itheima.annotation包中,创建UserService接口的实现类UserServiceImpl,该类需要实现接口中的save()方法,如文件4所示。

文件4 UserServiceImpl.java

 1    package com.itheima.annotation;
 2    import javax.annotation.Resource;
 3    import org.springframework.stereotype.Service;
 4    @Service("userService") 
 5    public class UserServiceImpl implements UserService{
 6        @Resource(name="userDao") 
 7        private UserDao userDao;
 8        public void save() {
 9             //调用userDao中的save方法
 10            this.userDao.save();
 11            System.out.println("userservice....save...");
 12        }
 13    }

在文件4中,首先使用@Service注解将UserServiceImpl类标识为Spring中的Bean,这相当于配置文件中<bean id="userService" class="com.itheima.annotation.UserServiceImpl" />的编写;然后使用@Resource注解标注在属性userDao上,这相当于配置文件中<property name="userDao" ref="userDao"/>的写法;最后在该类的save()方法中调用userDao中的save()方法,并输出一句话。

(5)在com.itheima.annotation包中,创建控制器类UserController,编辑后如文件5所示。

文件5 UserController.java

 1    package com.itheima.annotation;
 2    import javax.annotation.Resource;
 3    import org.springframework.stereotype.Controller;
 4    @Controller("userController")
 5    public class UserController {
 6        @Resource(name="userService")
 7        private UserService userService;
 8        public void save(){
 9            this.userService.save();
 10            System.out.println("userController...save...");
 11        }
 12    }

在文件5中,首先使用@Controller注解标注了UserController类,这相当于在配置文件中编写<bean id="userController" class="com.itheima.annotation.UserController"/>;然后使用了@Resource注解标注在userService属性上,这相当于在配置文件中编写<property name="userService" ref="userService" />;最后在其save()方法中调用了userService中的save()方法,并输出一句话。

(6)在com.itheima.annotation包中,创建配置文件beans6.xml,在配置文件中编写基于Annotation装配的代码,如文件6所示。

文件6 beans6.xml

 1    <?xml version="1.0" encoding="UTF-8"?>
 2    <beans xmlns="http://www.springframework.org/schema/beans"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4          xmlns:context="http://www.springframework.org/schema/context"
 5          xsi:schemaLocation="http://www.springframework.org/schema/beans 
 6          http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 7          http://www.springframework.org/schema/context 
 8      http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 9         <!-- 使用 context 命名空间 ,在配置文件中开启相应的注解处理器 -->
 10         <context:annotation-config />
 11         <!--分别定义3个Bean实例  -->
 12          <bean id="userDao" class="com.itheima.annotation.UserDaoImpl" />
 13          <bean id="userService" 
 14              class="com.itheima.annotation.UserServiceImpl" />
 15          <bean id="userController" 
 16              class="com.itheima.annotation.UserController" />
 17    </beans>

从上述代码可以看出,文件6与之前的配置文件有很大不同。首先,在<beans>元素中,增加了第4行,第7行和第8行中包含有context的约束信息;然后通过配置<context:annotation-config />来开启注解处理器;最后分别定义了3个Bean对应所编写的3个实例。与XML装备方式有所不同的是,这里不再需要配置子元素<property>。

上述Spring配置文件中的注解方式虽然较大程度简化了XML文件中Bean的配置,但仍需要在Spring配置文件中一一配置相应的Bean,为此Spring注解提供了另外一种高效的注解配置方式(对包路径下的所有Bean文件进行扫描),其配置方式如下:

<context:component-scan base-package="Bean所在的包路径"/>

所以可以将上述文件2-19中第9-16行代码进行如下替换(推荐):

  <!--使用 context 命名空间 ,通知Spring扫描指定包下所有Bean类,进行注解解析-->  
   <context:component-scan base-package="com.itheima.annotation" />

注意:

Spring4.0以上版本使用上面的代码对指定包中的注解进行扫描前,需要先向项目中导入Spring AOP的JAR包spring-aop-4.3.6.RELEASE.jar,否则程序在运行时会报出“java.lang.NoClassDefFoundError: org/springframework/aop/TargetSource”错误。

(7)在com.itheima.annotation包中,创建测试类AnnotationAssembleTest,在类中编写测试方法并定义配置文件的路径,然后通过Spring容器加载配置文件并获取UserController实例,最后调用实例中的save()方法,如文件7所示。

文件7 AnnotationAssembleTest.java

 1    package com.itheima.annotation;
 2    import org.springframework.context.ApplicationContext;
 3    import 
 4       org.springframework.context.support.ClassPathXmlApplicationContext;
 5    public class AnnotationAssembleTest {
 6        public static void main(String[] args) {
 7            // 定义配置文件路径
 8            String xmlPath = "com/itheima/annotation/beans6.xml";
 9            // 加载配置文件
 10            ApplicationContext applicationContext = 
 11                    new ClassPathXmlApplicationContext(xmlPath);
 12            // 获取UserController实例
 13            UserController userController = 
 14              (UserController) applicationContext.getBean("userController");
 15            // 调用UserController中的save()方法
 16            userController.save();
 17        }
 18    } 

执行程序后,控制台的输出结果如图1所示。

图1 运行结果

从图1可以看到,Spring容器已成功获取了UserController的实例,并通过调用实例中的方法执行了各层中的输出语句,这说明已成功实现了基于Annotation装配Bean。

小提示:

上述案例中如果使用@Autowired注解替换@Resource注解,也可以达到同样的效果。

点击此处
隐藏目录