• @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分

  • 相关阅读:
    设计模式-17-迭代器
    设计模式-16-备忘录
    微服务架构设计
    数据库拆分案例
    生成多个git ssh密钥
    分布式数据中间件TDDL、Amoeba、Cobar、MyCAT架构比较
    maven工程 java 实现文件上传 SSM ajax异步请求上传
    MySQL的分区、分表、集群
    Redis实现分布式锁原理与实现分析
    关于消息队列的使用
  • 原文地址:https://www.cnblogs.com/MaxElephant/p/8086810.html
Copyright © 2020-2023  润新知