@Component 元注解


@Component 元注解

這是一個元注解,意思是它可以用於標注其他注解,被它標注的注解和它起到相同或者類似的作用。Spring用它定義了其他具有特定意義的注解如@Controller @Service @Repository。如下是Spring中 @Service的定義:

    @Target({ElementType.TYPE})  
        @Retention(RetentionPolicy.RUNTIME)  
        @Documented  
        @Component // Spring will see this and treat @Service in the same way as @Component  
        public @interface Service {  
        }  

 

另外@Controller 和 @Repository與之類似。Spring在web項目賦予這些注解特殊的含義。分別表示控制器和 數據訪問層。
自定義

我們可以自定義注解,如下:

    @Target(ElementType.TYPE)  
    @Retention(RetentionPolicy.RUNTIME)  
    @Documented  
    @Component  
    public @interface MyComponent {  
    String value();  
    }  

 

使用

我們現在可以使用(自定義)注解直接標注在某個類上,此類就會自動的被Spring容器注冊為BeanDefinition,我們可以對上篇文章中在xml中定義的bean改也注解的方式進行聲明:

//使用元注解  
    @Component("user1")  
    public class UserServiceIml1 implements UserService{  

        private UserDao userDao;  
        @Override  
        public List<User> getUser() {  
           return userDao.getUser();  
        }  
        //標注在set方法上。  
        @Autowired  
        public void setUserDao(@Qualifier("userDao") UserDao userDao) {  
           this.userDao = userDao;  
        }  
    }  

 

 //使用自定義注解  
    @MyComponent("user2")  
    public class UserServiceIml2 implements UserService{  
        //標注在字段上。  
        @Autowired  
        @Qualifier("userDao")  
        private UserDao userDao;  
        @Override  
        public List<User> getUser() {  
           return userDao.getUser();  
        }  

    }  

 以上使用注解后,我們需要做一些配置是Spring啟用類路徑掃描(classpath-scan),在XML配置中加入以下配置,這個配置就自動啟用了注解的相關功能:

<context:component-scan base-package="com.test"/>  

 

以上注解表示自動掃描com.test包及其子包下被@component(或者其擴展)表中的類,並把他們注冊為bean。以上配置還有其他屬性,可以定義專門的過濾器做自定義的配置。

以下為一個示例:

<context:component-scan base-package="org.example">  
            <context:include-filter type="regex"  
                    expression=".*Stub.*Repository"/>  
            <context:exclude-filter type="annotation"  
                    expression="org.springframework.stereotype.Repository"/>  
</context:component-scan>  

 

@Bean

在采用XML配置bean的時候,我們可以使用實例工廠來定義一個Bean,采用@Bean注解我們也可以做到類似的形式。在一個Bean中定義另外一個Bean。這通過在@Component的標注類中對某個方法使用@Bean進行注解。

如下所示:

@Bean(name="getService")  
@Qualifier("getService")  
public UserService getService(@Qualifier("userDao") UserDao user){  
          UserService ser = new UserServiceIml1();  

          return ser;  
}  

 

上述定義一個Bean,並定義了Name和Qualifier屬性。還可以定義Scope,Lazy等屬性。見下個小節。

其實@Bean更多的是與@Confuguration一起使用,來構建另外一種不同於基於XML的ApplicationContext,即基於注解的,AnnotationConfigApplicationContext。這個以后討論。

命名和其他屬性

命名

基於@Componet及其擴展(如@Servic和自定義等)標注和classpath-scan定義的Bean,注解有一個value屬性,如果提供了,那么就此Bean的名字。如果不提供。就會使用Spring默認的命名機制,即簡單類名且第一個字母小寫,見如下示例:

  @Component("user5")  
    //Bean的名稱是user5  
    public class UserServiceIml5 implements UserService{  
    }  

    @Component()  
    //Bean的名稱是userServiceIml3  
    public class UserServiceIml3 implements UserService{  
    }  

 我們可以更新Spring默認的命名機制,只要我們實現了相關接口BeanNameGenerator,並進行配置,如下:

<context:component-scan base-package="org.example"  
            name-generator="org.example.MyNameGenerator" />  

 

其他

在基於XML的配置中bean標簽還有很多屬性,如scope、Lazy、init-method、depends-on、Qualifier等。下面通過一個簡單的配置例子說明:

 package com.test.service;  

    import java.util.List;  

    import org.springframework.beans.factory.annotation.Autowired;  
    import org.springframework.beans.factory.annotation.Qualifier;  
    import org.springframework.context.annotation.Bean;  
    import org.springframework.context.annotation.DependsOn;  
    import org.springframework.context.annotation.Lazy;  
    import org.springframework.context.annotation.Scope;  
    import org.springframework.context.annotation.ScopedProxyMode;  
    import org.springframework.stereotype.Component;  

    import com.test.bo.User;  
    import com.test.dao.UserDao;  
    import com.test.dao.UserDaoImp;  
    import com.test.service.UserService;  
    //使用元注解  
    @Component("user1")  
    @Qualifier("user1")  
    @Lazy(true)  
    @DependsOn("userDao")  
    public class UserServiceIml1 implements UserService{  

       private UserDao userDao;  
       @Override  
       public List<User> getUser() {  

          return userDao.getUser();  
       }  
       //標注在set方法上。  
       @Autowired  
       public void setUserDao(@Qualifier("userDao") UserDao userDao) {  
          this.userDao = userDao;  
       }  



       @Bean(name="getService",initMethod="init1",destroyMethod="close1")  
       @Qualifier("getService")  
       @Scope(value="singleton")  
       @Lazy(true)  
       @DependsOn("getDao")  
       public UserService getService(@Qualifier("getDao") UserDao user){  
          System.out.println("------------getService is creted when used--------------");  
          System.out.println(user.getClass().toString());  
          UserService ser = new UserServiceIml1();  
          return ser;  
       }  


       @Bean(name = "getDao")  
       @Qualifier("getDao")  
       @Scope(value="prototype",proxyMode=ScopedProxyMode.TARGET_CLASS)  
       @Lazy(true)  
       public UserDao getDao(){  
          System.out.println("------------getDao is creted when used--------------");  
          return new UserDaoImp();  
       }  


       private void init1(){  
          System.out.println("---------getService init1----------------");  

       }  

       private void close1(){  
          System.out.println("---------getService close----------------");  
       }  
       public UserDao getUserDao() {  
          return userDao;  
       }  


    }  

 

上述分別在類上和某個方法上,加入了很多的屬性配置,可以和傳統的XMl的配置比較。主要singleton引用其他類型時,需要生成代理。

@Configuration

Spring提供一種基於注解的applicationContext,實際應用中,它可以和XML的配置聯合使用或者各自單獨使用。當使用時,需要很大的利用的@Bean注解。

下面給一個簡單的例子,其他的詳細例子見Spring官方文檔。

首先是一個@Configuration 的配置類,定義了兩個Bean。

 @Configuration  
    public class MyAnnoConfig {  

       @Bean(name="cDao1")  
       public UserDao getConfigDao(){  
          return new UserDaoImp();  
       }  

       @Bean(name="cs1")  
       public UserService getConfigS(@Qualifier("cDao1") UserDao dao){  

          UserServiceIml us =new UserServiceIml();  
          us.setUserDao(dao);  
          return us;  
       }  


}  

 下面是測試函數。

 public class TestAnnoContextMain {  

       public static void main(String[] args) {  
          ApplicationContext  ctx = new AnnotationConfigApplicationContext(MyAnnoConfig.class);  

          UserService us = ctx.getBean("cs1",UserService.class);  
          System.out.println(us.getUser());  
       }  
}  

 

總結

本篇較詳細的說明了Spring支持的Bean級別的注解的使用方法,主要介紹了@Component和@Bean(在@component中使用),並穿插介紹了一些Bean屬性的注解。最后注意舉例說明Spring的基於注解的applicationContext和@configuration。

注意,本篇沒有介紹JSR-330的注解@Named,其和@Component基本一致,但不如前者強大。並且我認為只要比較清楚的一種方式的原理和使用方法,其他的都是舉一反三的例子=,這也是不詳細寫@configuration的原因(其實它和@Bean配合,和基於XML的配置的功能幾乎一樣)。本完整測試代碼0分

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM