spring之注解(三)Component

上篇文章中比较详细的介绍了依赖注入的相关注解,尤其是@Autowired。但是我们对bean的定义声明还是放在xml的配置文件中。spring当然提供了机制可以自动的扫描类路径,自动的向容器注册BeanDefinition。这就是Bean级别的注解。以上机制称为类路径扫描(clsspath-sacn),它是有相关注解(如@Component @Named @Bean)和beanFactoryPostProcessor和BeanPostProcessor实现的。本篇文章我们依次对各个注解进行说明。

本篇使用的示例代码继承之前的篇章。首先看注解。

@Component

元注解

这是一个元注解,意思是它可以用于标注其他注解,被它标注的注解和它起到相同或者类似的作用。Spring用它定义了其他具有特定意义的注解如@Controller @Service @Repository。如下是Spring中 @Service的定义:

[java]  view plain  copy
  1. @Target({ElementType.TYPE})  
  2.     @Retention(RetentionPolicy.RUNTIME)  
  3.     @Documented  
  4.     @Component // Spring will see this and treat @Service in the same way as @Component  
  5.     public @interface Service {  
  6.     }  

另外@Controller  和 @Repository与之类似。Spring在web项目赋予这些注解特殊的含义。分别表示控制器和 数据访问层。

自定义

  我们可以自定义注解,如下:

[java]  view plain  copy
  1. @Target(ElementType.TYPE)  
  2. @Retention(RetentionPolicy.RUNTIME)  
  3. @Documented  
  4. @Component  
  5. public @interface MyComponent {  
  6. String value();  
  7. }  

使用

我们现在可以使用(自定义)注解直接标注在某个类上,此类就会自动的被Spring容器注册为BeanDefinition,我们可以对上篇文章中在xml中定义的bean改也注解的方式进行声明:

[java]  view plain  copy
  1. //使用元注解  
  2. @Component("user1")  
  3. public class UserServiceIml1 implements UserService{  
  4.      
  5.     private UserDao userDao;  
  6.     @Override  
  7.     public List<User> getUser() {  
  8.        return userDao.getUser();  
  9.     }  
  10.     //标注在set方法上。  
  11.     @Autowired  
  12.     public void setUserDao(@Qualifier("userDao") UserDao userDao) {  
  13.        this.userDao = userDao;  
  14.     }  
  15. }  

[java]  view plain  copy
  1. //使用自定义注解  
  2. @MyComponent("user2")  
  3. public class UserServiceIml2 implements UserService{  
  4.     //标注在字段上。  
  5.     @Autowired  
  6.     @Qualifier("userDao")  
  7.     private UserDao userDao;  
  8.     @Override  
  9.     public List<User> getUser() {  
  10.        return userDao.getUser();  
  11.     }  
  12.      
  13. }  

以上使用注解后,我们需要做一些配置是Spring启用类路径扫描(classpath-scan),在XML配置中加入以下配置,这个配置就自动启用了注解的相关功能:

[html]  view plain  copy
  1. <context:component-scan base-package="com.test"/>  


以上注解表示自动扫描com.test包及其子包下被@component(或者其扩展)表中的类,并把他们注册为bean。以上配置还有其他属性,可以定义专门的过滤器做自定义的配置。

以下为一个示例:

[html]  view plain  copy
  1. <context:component-scan base-package="org.example">  
  2.         <context:include-filter type="regex"  
  3.                 expression=".*Stub.*Repository"/>  
  4.         <context:exclude-filter type="annotation"  
  5.                 expression="org.springframework.stereotype.Repository"/>  
  6.     </context:component-scan>  

@Bean

在采用XML配置bean的时候,我们可以使用实例工厂来定义一个Bean,采用@Bean注解我们也可以做到类似的形式。在一个Bean中定义另外一个Bean。这通过在@Component的标注类中对某个方法使用@Bean进行注解。

如下所示:

[java]  view plain  copy
  1. @Bean(name="getService")  
  2.    @Qualifier("getService")  
  3.    public UserService getService(@Qualifier("userDao") UserDao user){  
  4.       UserService ser = new UserServiceIml1();  
  5.        
  6.       return ser;  
  7.    }  

上述定义一个Bean,并定义了Name和Qualifier属性。还可以定义Scope,Lazy等属性。见下个小节。

其实@Bean更多的是与@Confuguration一起使用,来构建另外一种不同于基于XML的ApplicationContext,即基于注解的,AnnotationConfigApplicationContext。这个以后讨论。

命名和其他属性

命名

基于@Componet及其扩展(如@Servic和自定义等)标注和classpath-scan定义的Bean,注解有一个value属性,如果提供了,那么就此Bean的名字。如果不提供。就会使用Spring默认的命名机制,即简单类名且第一个字母小写,见如下示例:

[java]  view plain  copy
  1. @Component("user5")  
  2. //Bean的名称是user5  
  3. public class UserServiceIml5 implements UserService{  
  4. }  
  5.    
  6. @Component()  
  7. //Bean的名称是userServiceIml3  
  8. public class UserServiceIml3 implements UserService{  
  9. }  

 我们可以更新Spring默认的命名机制,只要我们实现了相关接口BeanNameGenerator,并进行配置,如下:

[html]  view plain  copy
  1. <context:component-scan base-package="org.example"  
  2.         name-generator="org.example.MyNameGenerator" />  

其他

在基于XML的配置中bean标签还有很多属性,如scope、Lazy、init-method、depends-on、Qualifier等。下面通过一个简单的配置例子说明:

[java]  view plain  copy
  1. package com.test.service;  
  2.    
  3. import java.util.List;  
  4.    
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.beans.factory.annotation.Qualifier;  
  7. import org.springframework.context.annotation.Bean;  
  8. import org.springframework.context.annotation.DependsOn;  
  9. import org.springframework.context.annotation.Lazy;  
  10. import org.springframework.context.annotation.Scope;  
  11. import org.springframework.context.annotation.ScopedProxyMode;  
  12. import org.springframework.stereotype.Component;  
  13.    
  14. import com.test.bo.User;  
  15. import com.test.dao.UserDao;  
  16. import com.test.dao.UserDaoImp;  
  17. import com.test.service.UserService;  
  18. //使用元注解  
  19. @Component("user1")  
  20. @Qualifier("user1")  
  21. @Lazy(true)  
  22. @DependsOn("userDao")  
  23. public class UserServiceIml1 implements UserService{  
  24.     
  25.    private UserDao userDao;  
  26.    @Override  
  27.    public List<User> getUser() {  
  28.        
  29.       return userDao.getUser();  
  30.    }  
  31.    //标注在set方法上。  
  32.    @Autowired  
  33.    public void setUserDao(@Qualifier("userDao") UserDao userDao) {  
  34.       this.userDao = userDao;  
  35.    }  
  36.     
  37.     
  38.     
  39.    @Bean(name="getService",initMethod="init1",destroyMethod="close1")  
  40.    @Qualifier("getService")  
  41.    @Scope(value="singleton")  
  42.    @Lazy(true)  
  43.    @DependsOn("getDao")  
  44.    public UserService getService(@Qualifier("getDao") UserDao user){  
  45.       System.out.println("------------getService is creted when used--------------");  
  46.       System.out.println(user.getClass().toString());  
  47.       UserService ser = new UserServiceIml1();  
  48.       return ser;  
  49.    }  
  50.     
  51.     
  52.    @Bean(name = "getDao")  
  53.    @Qualifier("getDao")  
  54.    @Scope(value="prototype",proxyMode=ScopedProxyMode.TARGET_CLASS)  
  55.    @Lazy(true)  
  56.    public UserDao getDao(){  
  57.       System.out.println("------------getDao is creted when used--------------");  
  58.       return new UserDaoImp();  
  59.    }  
  60.     
  61.     
  62.    private void init1(){  
  63.       System.out.println("---------getService init1----------------");  
  64.    
  65.    }  
  66.     
  67.    private void close1(){  
  68.       System.out.println("---------getService close----------------");  
  69.    }  
  70.    public UserDao getUserDao() {  
  71.       return userDao;  
  72.    }  
  73.     
  74.     
  75. }  

上述分别在类上和某个方法上,加入了很多的属性配置,可以和传统的XMl的配置比较。主要singleton引用其他类型时,需要生成代理。

@Configuration

Spring提供一种基于注解的applicationContext,实际应用中,它可以和XML的配置联合使用或者各自单独使用。当使用时,需要很大的利用的@Bean注解。

下面给一个简单的例子,其他的详细例子见Spring官方文档。

首先是一个@Configuration 的配置类,定义了两个Bean。

[java]  view plain  copy
  1. @Configuration  
  2. public class MyAnnoConfig {  
  3.    
  4.    @Bean(name="cDao1")  
  5.    public UserDao getConfigDao(){  
  6.       return new UserDaoImp();  
  7.    }  
  8.     
  9.    @Bean(name="cs1")  
  10.    public UserService getConfigS(@Qualifier("cDao1") UserDao dao){  
  11.        
  12.       UserServiceIml us =new UserServiceIml();  
  13.       us.setUserDao(dao);  
  14.       return us;  
  15.    }  
  16.     
  17.     
  18. }  

下面是测试函数。

[java]  view plain  copy
  1. public class TestAnnoContextMain {  
  2.    
  3.    public static void main(String[] args) {  
  4.       ApplicationContext  ctx = new AnnotationConfigApplicationContext(MyAnnoConfig.class);  
  5.        
  6.       UserService us = ctx.getBean("cs1",UserService.class);  
  7.       System.out.println(us.getUser());  
  8.    }  
  9. }  

总结

本篇较详细的说明了Spring支持的Bean级别的注解的使用方法,主要介绍了@Component和@Bean(在@component中使用),并穿插介绍了一些Bean属性的注解。最后注意举例说明Spring的基于注解的applicationContext和@configuration。

注意,本篇没有介绍JSR-330的注解@Named,其和@Component基本一致,但不如前者强大。并且我认为只要比较清楚的一种方式的原理和使用方法,其他的都是举一反三的例子=,这也是不详细写@configuration的原因(其实它和@Bean配合,和基于XML的配置的功能几乎一样)。本完整测试代码0分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值