zoukankan      html  css  js  c++  java
  • JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(10):通过注解(annotation)装配Bean之(@Configguration、@Component、@Value、@ComponentScan、@Autowired、@Primary、@Qualifier、@Bean)

    一、通过注解(annotation)装配Bean
    通过之前的学习,我们已经知道如何使用XML装配Bean,但是更多的时候已经不再推荐使用XML的方式去装配Bean,更多的时候会考虑注解(annotation)的方式去装配Bean。
    使用注解的方式可以减少XML的配置,注解功能更为强大,它既能实现XML的功能,也能提供自动装配的功能,采用了自动装配后,程序员所需要做的决断就减少了,更加有利于对程序的开发,
    这就是"约定优于配置"的开发原则。
    在Spring中,它提供了两种方式来让Spring IoC容器发现Bean。
    1.组件扫描:通过定义资源的方式,让Spring IoC容器扫描对应的包,从而把Bean装配进来。
    2.自动装配:通过注解定义,使得一些依赖关系可以通过注解来完成。
    通过扫描和自动装配,大部分的工程师都可以使用Java配置完成,而不是XML,这样可以有效地减少配置和引入大量ML,它解决了在Spring3之前的版本需要大量的XML的配置的问题,
    这些问题曾被许多开发者诟病。由于目前注解已经成为Spring开发的主流,同时也必须了解不使用XML同样会存在一些弊端,比如系统存在多个公共配置文件(比如多个properties和xml文件),
    如果写在注解里,那么这些公共配置文件就会比较分散,这样 不利于统一的管理,又或者一些来至第三方的类,而不是我们系统开发的配置文件,这时利用xml配置就会比较容易管理。
    目前企业所流行的方式是,注解为主,xml为辅。

    1、使用@Component装配Bean
    @Component:代表Spring IoC容器会把这个类扫描生成Bean实例,其中value属性表示这个Bean的id,语法格式:@Component("beanId")或者@Component(value="beanId")
    @Value:代表值的注入,注入的时候Spring IoC会自动转型。
    @ComponentScan:代表进行扫描,默认是扫描当前把的路径,POJO的包名和它必须保持一致才能扫描,否则是不会自动装配Bean的。这里需要特别说明一下:

    @ComponentScan存在2个配置项:第一个是basePackages,它是由base和package两个单词组成的,而package还使用了复数,意味着它可以配置一个Java包的数组,Spring会根据他的配置
    扫描对应的包和子包,将配置好的Bean装配进来;第二个是basePackageClasses,他是由base,package,class三个单词组成,采用复数,意味着可以配置多个类,Spring可以根据配置的类所在的包
    进行扫描装配对应配置的Bean。

    贴出测试代码:

    ---------------------->以下着重测试注解:@Component、@Value()<-----------------------------

    创建一个:UserBean.java

     1 package com.xfwl.spring.annotation;
     2 
     3 import org.springframework.beans.factory.annotation.Value;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.stereotype.Component;
     6 
     7 /**
     8  * 测试注解:@Component装配Bean
     9  * @author Jason
    10  * 
    11  */
    12 @ComponentScan        //启动扫描当前所在包的Bean,注入Spring IoC容器
    13 @Component("user")    //注入user  //@Component("user")或者@Component(value="user")
    14 public class UserBean {
    15     @Value("xfww")
    16     private String uname;
    17     @Value("123456")
    18     private String upwd;
    19     public UserBean(){}
    20     public UserBean(String uname,String upwd){
    21         this.uname=uname;
    22         this.upwd=upwd;
    23     }
    24     public String getUname() {
    25         return uname;
    26     }
    27     public void setUname(String uname) {
    28         this.uname = uname;
    29     }
    30     public String getUpwd() {
    31         return upwd;
    32     }
    33     public void setUpwd(String upwd) {
    34         this.upwd = upwd;
    35     }
    36     @Override
    37     public String toString() {
    38         return "UserBean [uname=" + uname + ", upwd=" + upwd + "]";
    39     }        
    40 }    
    View Code

     创建一个:Manager.java

     1 package com.xfwl.spring.annotation;
     2 
     3 import java.util.List;
     4 import java.util.Map;
     5 import java.util.Properties;
     6 import java.util.Set;
     7 
     8 import org.springframework.beans.factory.annotation.Autowired;
     9 import org.springframework.stereotype.Component;
    10 /**
    11  * 注解测试:@Autoired 自动装配
    12  * @function  
    13  * @author 小风微凉
    14  * @time  2018-7-10 上午11:32:01
    15  */
    16 @Component("manager")
    17 public class Manager{
    18     @Autowired
    19     private long id;
    20     @Autowired
    21     private String mname;
    22     @Autowired
    23     private int mage;
    24     /******getter和setter***********/
    25     public long getId() {
    26         return id;
    27     }
    28     public void setId(long id) {
    29         this.id = id;
    30     }
    31     public String getMname() {
    32         return mname;
    33     }
    34     public void setMname(String mname) {
    35         this.mname = mname;
    36     }
    37     public int getMage() {
    38         return mage;
    39     }
    40     public void setMage(int mage) {
    41         this.mage = mage;
    42     }
    43 }
    View Code

     创建一个测试类:TestAnnotation.java

    package com.xfwl.spring.annotation;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    /**
     * Spring Ioc测试
     * @function  
     * @author 小风微凉
     * @time  2018-7-10 上午9:55:15
     */
    public class TestAnnotation {
        //项目相对路径
        private static final String xmlRelPath="com/xfwl/spring/assem/applicationContext.xml";
        public static void main(String[] args) {
            //通过注解拿到Spring IoC容器对象
            ApplicationContext ctx=new  AnnotationConfigApplicationContext(UserBean.class);
            //获取Bean对象
            UserBean user=(UserBean) ctx.getBean("user");        
            System.out.println(user.toString());
        }
    }

     测试结果:(上面注解正常运行

    1 log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
    2 log4j:WARN Please initialize the log4j system properly.
    3 log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    4 UserBean [uname=xfww, upwd=123456]

     ---------------------->以下着重测试注解:@ComponentScan<-----------------------------

    创建几个测试类如下:

    ComponScan_1.java 

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.context.annotation.Primary;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:55:26
    13  */
    14 @Component("serviceImp")
    15 //@Primary
    16 public class ServiceImpl implements IServices {
    17     @Autowired(required=true)    
    18     private UserBean user;
    19     @Override
    20     public void show() {    
    21         System.out.println(this.user.toString());
    22     }
    23     /**********getter和setter*******************/
    24     public UserBean getUser() {
    25         return user;
    26     }
    27     public void setUser(UserBean user) {
    28         this.user = user;
    29     }
    30 }
    View Code

      ComponScan_2.java

     1 package com.xfwl.spring.annotation.scans;
     2 
     3 import org.springframework.beans.factory.annotation.Value;
     4 import org.springframework.stereotype.Component;
     5 
     6 /**
     7  * 测试:
     8  * [1].扫描注解@ComponnetScan的属性basePackages和basePackageClasses配置项的使用
     9  * @function  
    10  * @author 小风微凉
    11  * @time  2018-7-12 上午9:16:15
    12  */
    13 @Component("scan_2")
    14 public class ComponScan_2 {
    15     @Value("scan_2_id")
    16     private String id;
    17     @Value("scan_2_info")
    18     private String info;
    19     /*******getter和setter************/
    20     public String getId() {
    21         return id;
    22     }
    23     public void setId(String id) {
    24         this.id = id;
    25     }
    26     public String getInfo() {
    27         return info;
    28     }
    29     public void setInfo(String info) {
    30         this.info = info;
    31     }
    32     /*******重写toString方法******************/
    33     @Override
    34     public String toString() {
    35         return "ComponScan_2 [id=" + id + ", info=" + info + "]";
    36     }    
    37 }
    View Code

     一个管理类:ScanManage.java,且这个类中,使用扫面注解:@ComponentScan(basePackageClasses={ComponScan_1.class,ComponScan_2.class,ScanManage.class}) 

     1 package com.xfwl.spring.annotation.scans;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.stereotype.Component;
     6 
     7 /**
     8  * 测试:
     9  * [1].扫描注解@ComponnetScan的属性basePackages和basePackageClasses配置项的使用。
    10  * [2].自动装配注解@Autowired,配置在属性字段或者属性字段对应的setter方法上。
    11  * @function  
    12  * @author 小风微凉
    13  * @time  2018-7-12 上午10:06:55
    14  */
    15 //配置注解
    16 @Component("scanManage")
    17 //第二种方式:配置指定的类,通过反射注入IoC
    18 @ComponentScan(basePackageClasses={ComponScan_1.class,ComponScan_2.class,ScanManage.class})
    19 public class ScanManage {
    20     @Autowired(required=true)
    21     private ComponScan_1 scan_1;
    22     private ComponScan_2 scan_2;
    23     /*******getter和setter************/
    24     public ComponScan_1 getScan_1() {
    25         return scan_1;
    26     }
    27     public void setScan_1(ComponScan_1 scan_1) {
    28         this.scan_1 = scan_1;
    29     }
    30     public ComponScan_2 getScan_2() {
    31         return scan_2;
    32     }
    33     @Autowired(required=true)
    34     public void setScan_2(ComponScan_2 scan_2) {
    35         this.scan_2 = scan_2;
    36     }
    37     /*******重写toString方法******************/
    38     @Override
    39     public String toString() {
    40         return "ScanManage [scan_1=" + scan_1.getId() + ", scan_2=" + scan_2.getId() + "]";
    41     }    
    42 }

     一个测试类:TestScan.java

     1 package com.xfwl.spring.annotation;
     2 
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
     5 
     6 import com.xfwl.spring.annotation.scans.ComponScan_1;
     7 import com.xfwl.spring.annotation.scans.ComponScan_2;
     8 import com.xfwl.spring.annotation.scans.ScanManage;
     9 import com.xfwl.spring.annotation.scans2.ScanManage2;
    10 
    11 public class TestScan {
    12     //项目相对路径
    13         private static final String xmlRelPath="com/xfwl/spring/assem/applicationContext.xml";
    14         public static void main(String[] args) {
    15             //通过注解拿到Spring IoC容器对象
    16             /**
    17              * ScanManage:使用了@ComponnetScan的basePackageClasses的配置项
    18              * ScanManage2:使用了@ComponnetScan的basePackages的配置项
    19              */
    20             //ApplicationContext ctx=new  AnnotationConfigApplicationContext(ScanManage.class);//不可以把@ComponentScan注解在接口中,会报错
    21             ApplicationContext ctx=new  AnnotationConfigApplicationContext(ScanManage2.class);
    22             //获取Bean对象
    23             ComponScan_1 scan1_1=(ComponScan_1) ctx.getBean("scan_1");        
    24             System.out.println(scan1_1.toString());
    25             ComponScan_2 scan1_2=(ComponScan_2) ctx.getBean("scan_2");        
    26             System.out.println(scan1_2.toString());
    27             ScanManage scan1Manage1=(ScanManage) ctx.getBean("scanManage");        
    28             System.out.println(scan1Manage1.toString());
    29         }
    30 }

     测试结果:以上加粗,红色的代码,均可以正常运行,说明注解正常在跑。

    总结一下:  

    不可以把@ComponentScan注解在接口中,会报错

     2、获取Spring IoC容器对象的2中形式:

    第一种:获取xml配置文件,产生Spring IoC容器对象,有如下几种形式。
    FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(xmlAbsPath);
    ApplicationContext ctx=new ClassPathXmlApplicationContext(xmlRelPath);
    ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext(xmlRelPath);
    第二种:通过注解获取Spring IoC容器对象
    ApplicationContext ctx=new AnnotationConfigApplicationContext(UserBean.class);
    特别说明:UserBean类中必须使用注解:@ComponentScan才可以扫描包下面的POJO装配Bean注入到Spring Ioc容器中。

     3、自动装配-@Autowired

    上面的注解都没有给Bean对象的属性注入对象,关于这个问题,在注解中略微有点复杂,在大部分情况下建议使用自动装配,因为这样可以减少配置的复杂度,
    所以这里先介绍自动装配。
    通过学习Spring IoC容器,我们知道Spring是先完成Bean的定义和生成,然后寻找需要注入的资源。也就是当Spring生成所有的Bean后,然后发现这个注解,
    它就会在Bean中查找,然后找到对应的类型,将其注入进来,这样就完成了依赖注入了。所谓自动装配技术是一种由Spring自己发现对应的Bean,自动完成装配工作的方式,
    它会应用到一个十分常用的注解@Autowrired,这个时候Spring IoC容器会自动根据类型去寻找定义的Bean然后将其注入。
    需要注意的是,一旦配置了@Autowrired,在Spring IoC容器中就必须存在对应bean对象,否则就会Bean查找失败,在默认的情况下寻找失败它就会抛出异常,也就是说默认
    情况下,Spring IoC容器会认为一定要找到对应的Bean来注入这个属性字段,有时候这并不是一个真实的需要,比如日志,有时候我们会觉得这个字段可有可无,这个时候可以通过
    @Autowired的配置项required来改变它,比如@Autowired(required=false)。

    以下贴出测试代码:

    @Autowired 注解普通属性字段:

     1 package com.xfwl.spring.annotation;
     2 
     3 import java.util.List;
     4 import java.util.Map;
     5 import java.util.Properties;
     6 import java.util.Set;
     7 
     8 import org.springframework.beans.factory.annotation.Autowired;
     9 import org.springframework.stereotype.Component;
    10 /**
    11  * 注解测试:@Autoired 自动装配
    12  * @function  
    13  * @author 小风微凉
    14  * @time  2018-7-10 上午11:32:01
    15  */
    16 @Component("manager")
    17 public class Manager{
    18     @Autowired
    19     private long id;
    20     @Autowired
    21     private String mname;
    22     @Autowired
    23     private int mage;
    24     /******getter和setter***********/
    25     public long getId() {
    26         return id;
    27     }
    28     public void setId(long id) {
    29         this.id = id;
    30     }
    31     public String getMname() {
    32         return mname;
    33     }
    34     public void setMname(String mname) {
    35         this.mname = mname;
    36     }
    37     public int getMage() {
    38         return mage;
    39     }
    40     public void setMage(int mage) {
    41         this.mage = mage;
    42     }
    43 }

     @Autowired 注解引用类型字段:

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.context.annotation.Primary;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:55:26
    13  */
    14 @Component("serviceImp")
    15 //@Primary
    16 public class ServiceImpl implements IServices {
    17     @Autowired(required=true)    
    18     private UserBean user;
    19     @Override
    20     public void show() {    
    21         System.out.println(this.user.toString());
    22     }
    23     /**********getter和setter*******************/
    24     public UserBean getUser() {
    25         return user;
    26     }
    27     public void setUser(UserBean user) {
    28         this.user = user;
    29     }
    30 }

           正如之前所谈到的在默认情况下是必须注入成功的,所以这里的required的默认值为true。当把配置修改为false时,就告诉Spring IoC容器,假如在已经定义好的Bean中查找
    不到的对应的类型,允许不注入,这样也就没有异常抛出,只是这个字段可能为空,开发者自行校验,以免发生空指针异常。在大部分情况下,都不需要这样修改。
    @Autowired除可以配置在属性字段上外,还可以配置在方法上,常见的Bean的setter方法也可以使用它完成注入。 

    1     private UserBean user;
    2     /**********getter和setter*******************/
    3     @Autowired(required=true)
    4     public void setUser(UserBean user) {
    5         this.user = user;
    6     }

            在大部分配置中,推荐使用@Autowired注解,这是Spring IoC容器自动装配完成的,使得配置大幅度减少,满足约定优于配置的原则,增强程序的健壮性。 

    4、自动装配的歧义性(@Primary和@Qualifier)
            上面谈到了@Autowired注解,它可以完成一些自动装配功能,并且使用方式十分简单,但是有时候这样的当时并不能使用。这一切的根源来至于按类型的方式,按照Spring的建议,
    在大部分情况下会使用接口编程,但是定义一个接口,并不一定只有一个与之对应的实现类。换句话说,一个接口可以有多个实现类。
    下面介绍2中消除歧义性的注解,其消除歧义性的理念也不同:
    第一种注解@Primary:
    注解@Primary代表首要的,当Spring IoC通过一个接口或者抽象类注入对象的时候,由于存在多个实现类或者具体类,就会犯糊涂,不知道采用哪个类为好。
    注解@Primary则是告诉Spring IoC容器,请优先该类注入。也就是说,使用了@Primary注解的类将被Spring IoC容器作为优先选择被注入,这样可以消除歧义性。
    同样的,或许你会想到将@Primary注解到同一个接口的多个实现类中,这样就会存在多个首选的接口了,但是在Spring IoC容器中这样的定义是允许的,只是在注入的时候将
    会抛出异常。但是无论如何@Primary只能解决首要性的问题,而不能解决选择性的问题,简而言之,它不能选择使用接口具体的实现类去注入,仅仅提供一个首要性的选择倾向。

    创建2个实现同一个接口的实现子类:

    实体POJO类:UserBean.java

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Value;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.stereotype.Component;
     6 
     7 /**
     8  * 测试注解:@Component装配Bean
     9  * @author Jason
    10  * 
    11  */
    12 @Component("user")    //注入user  //@Component("user")或者@Component(value="user")
    13 public class UserBean {
    14     @Value("xfww")
    15     private String uname;
    16     @Value("123456")
    17     private String upwd;
    18     public UserBean(){}
    19     public UserBean(String uname,String upwd){
    20         this.uname=uname;
    21         this.upwd=upwd;
    22     }
    23     public String getUname() {
    24         return uname;
    25     }
    26     public void setUname(String uname) {
    27         this.uname = uname;
    28     }
    29     public String getUpwd() {
    30         return upwd;
    31     }
    32     public void setUpwd(String upwd) {
    33         this.upwd = upwd;
    34     }
    35     @Override
    36     public String toString() {
    37         return "UserBean [uname=" + uname + ", upwd=" + upwd + "]";
    38     }    
    39     
    40 }    
    View Code

     接口:IServices.java 

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.context.annotation.ComponentScan;
     4 import org.springframework.stereotype.Component;
     5 
     6 /**
     7  * 服务接口:测试注解@Qualifier
     8  * @function  
     9  * @author 小风微凉
    10  * @time  2018-7-12 上午11:52:29
    11  */
    12 @Component(value="service")
    13 public interface IServices {
    14     public void show();
    15 }

     第一个实现子类:ServiceImpl.java 

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.context.annotation.Primary;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:55:26
    13  */
    14 @Component("serviceImp")
    15 @Primary
    16 public class ServiceImpl implements IServices {
    17     @Autowired(required=true)    
    18     private UserBean user;
    19     @Override
    20     public void show() {    
    21         System.out.println(this.user.toString());
    22     }
    23     /**********getter和setter*******************/
    24     public UserBean getUser() {
    25         return user;
    26     }
    27     public void setUser(UserBean user) {
    28         this.user = user;
    29     }
    30 }

     第二个实现子类:ServiceImpl2.java(在此类中使用注解@Primary

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.context.annotation.Primary;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:55:26
    13  */
    14 @Component("serviceImp")
    15 @Primary
    16 public class ServiceImpl implements IServices {
    17     @Autowired(required=true)    
    18     private UserBean user;
    19     @Override
    20     public void show() {    
    21         System.out.println(this.user.toString());
    22     }
    23     /**********getter和setter*******************/
    24     public UserBean getUser() {
    25         return user;
    26     }
    27     public void setUser(UserBean user) {
    28         this.user = user;
    29     }
    30 }

     在创建一个逻辑管理类:UserManage.java(在此类中添加注解扫描器)

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.beans.factory.annotation.Qualifier;
     5 import org.springframework.context.annotation.ComponentScan;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:58:56
    13  */
    14 @Component("manager")
    15 @ComponentScan(basePackages={"com.xfwl.spring.annotation.qualifier"})//启动扫描当前所在包的Bean,注入Spring IoC容器
    16 public class UserManage {
    17     @Autowired(required=true)
    18     //@Qualifier("serviceImp2")
    19     private IServices service;
    20     
    21     public void show(){
    22         this.service.show();
    23     }
    24     /**********getter和setter*******************/
    25     public IServices getService() {
    26         return service;
    27     }
    28     public void setService(IServices service) {
    29         this.service = service;
    30     }
    31 }

     再来一个测试类:TestScan.java

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
     5 
     6 import com.xfwl.spring.annotation.scans.ComponScan_1;
     7 import com.xfwl.spring.annotation.scans.ComponScan_2;
     8 import com.xfwl.spring.annotation.scans.ScanManage;
     9 import com.xfwl.spring.annotation.scans2.ScanManage2;
    10 
    11 public class TestScan {
    12     //项目相对路径
    13         private static final String xmlRelPath="com/xfwl/spring/assem/applicationContext.xml";
    14         public static void main(String[] args) {            
    15             ApplicationContext ctx=new  AnnotationConfigApplicationContext(UserManage.class);
    16             //获取Bean对象
    17             UserManage manager=(UserManage) ctx.getBean("manager");        
    18             manager.show();
    19         }
    20 }

     测试结果:注解正常运行

    第二种注解@Qualifier:
    正如上面谈及到的歧义性,一个重要的原因是Spring在寻找依赖注入的时候采用按类型注入引起的。处理按照类型查找Bean,Spring IoC容器最底层的接口BeanFactory,
    也定义了按照名称查找的方法,如果采用名称查找的方法,而不是采用类型查找,那么不就可以消除歧义性了吗?答案是肯定的!而注解@Qualifier就是这样一个注解。

     测试代码如下:(由于注解@Primary和注解@Qualifier的测试代码及其相似,所以以下会修改上面的代码来完成测试

    修改ServiceImpl.java,修改部分如下:

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.context.annotation.Primary;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:55:26
    13  */
    14 @Component("serviceImp")
    15 //@Primary
    16 public class ServiceImpl implements IServices {
    17     @Autowired(required=true)    
    18     private UserBean user;
    19     @Override
    20     public void show() {    
    21         System.out.println(this.user.toString());
    22     }
    23     /**********getter和setter*******************/
    24     public UserBean getUser() {
    25         return user;
    26     }
    27     public void setUser(UserBean user) {
    28         this.user = user;
    29     }
    30 }
    View Code

     在UserManage.java中指定:@Qualifier("serviceImp2") 

     1 package com.xfwl.spring.annotation.qualifier;
     2 
     3 import org.springframework.beans.factory.annotation.Autowired;
     4 import org.springframework.beans.factory.annotation.Qualifier;
     5 import org.springframework.context.annotation.ComponentScan;
     6 import org.springframework.stereotype.Component;
     7 
     8 /**
     9  * 测试注解@Qualifier
    10  * @function  
    11  * @author 小风微凉
    12  * @time  2018-7-12 上午11:58:56
    13  */
    14 @Component("manager")
    15 @ComponentScan(basePackages={"com.xfwl.spring.annotation.qualifier"})//启动扫描当前所在包的Bean,注入Spring IoC容器
    16 public class UserManage {
    17     @Autowired(required=true)
    18     @Qualifier("serviceImp2")
    19     private IServices service;
    20     
    21     public void show(){
    22         this.service.show();
    23     }
    24     /**********getter和setter*******************/
    25     public IServices getService() {
    26         return service;
    27     }
    28     public void setService(IServices service) {
    29         this.service = service;
    30     }
    31 }

     测试结果:注解正常运行

    5、装载带有参数的构造方法类:

    贴出测试代码: 

     1 package com.xfwl.spring.annotation.qualifier;
     2 import org.springframework.beans.factory.annotation.Autowired;
     3 import org.springframework.stereotype.Component;
     4 @Component("serviceImp")
     5 public class ServiceImpl implements IServices {
     6     private UserBean user;
     7     public ServiceImpl(@Autowired UserBean user){//测试通过
     8         this.user=user;
     9     }
    10     @Override
    11     public void show() {    
    12         System.out.println(this.user.toString());
    13     }
    14 }

     或者 

     1 package com.xfwl.spring.annotation.qualifier;
     2 import org.springframework.beans.factory.annotation.Qualifier;
     3 import org.springframework.stereotype.Component;
     4 @Component("serviceImp3")
     5 public class ServiceImpl3 implements IServices {
     6     private UserBean user;
     7     public ServiceImpl3(@Qualifier UserBean user){//测试不通过,不支持注解@Qualifier注入构造器的参数
     8         this.user=user;
     9     }
    10     @Override
    11     public void show() {    
    12         System.out.println(this.user.toString());
    13     }
    14 }

     从上面的代码,可以看出:这种注解并没有放在属性字段或者属性的setter方法上,而是直接放在构造器上的。

    6、使用@Bean装配Bean

          以上描述的用法都是通过@Componnet注解装配Bean,但是@Componnet只能注解在类上,不能注解在方法上。对于Java而言,大部分的开发都需要引入第三方的包(Jar文件),而且往往
    并没有这些包的源码,这时候无法为这些包的类加入@Componnet注解,让他们变为开发环境的Bean.你可以使用新类扩展(extends)其包内的类,然后在新类上使用@Componnet,但是这样又显得
    不伦不类。
         这个时候Spring给与一个注解@Bean,它可以注解到方法上,并且讲方法返回的对象作为Spring的Bean存放在IoC容器中。比如我们需要用到的DBCP数据源。

    现在来测试一下:

     1 package com.xfwl.spring.annotation.bean;
     2 
     3 import java.util.Properties;
     4 
     5 import javax.sql.DataSource;
     6 
     7 import org.apache.commons.dbcp2.BasicDataSourceFactory;
     8 import org.springframework.context.annotation.Bean;
     9 import org.springframework.context.annotation.ComponentScan;
    10 
    11 @ComponentScan(basePackages={"com.xfwl.spring.annotation.bean"})
    12 public class ManagerScan {
    13     @Bean(name="ds")
    14     public DataSource getDataSource(){
    15         Properties props=new Properties();
    16         props.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
    17         props.setProperty("url", "jdbc:oracle:thin:@***.**.17.33:1521:**");
    18         props.setProperty("username", "***");
    19         props.setProperty("password", "***");
    20         DataSource dataSource=null;
    21         try {
    22             dataSource=BasicDataSourceFactory.createDataSource(props);
    23         } catch (Exception e) {
    24             e.printStackTrace();
    25         }
    26         return dataSource;        
    27     }
    28 }

     以及

     1 package com.xfwl.spring.annotation.bean;
     2 import java.util.Properties;
     3 
     4 import javax.sql.DataSource;
     5 import org.apache.commons.dbcp2.BasicDataSourceFactory;
     6 import org.springframework.context.ApplicationContext;
     7 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
     8 import org.springframework.context.annotation.Bean;
     9 import org.springframework.context.annotation.ComponentScan;
    10 import org.springframework.stereotype.Component;
    11 @Component("test")
    12 public class TestBean {
    13     public static void main(String[] args) {        
    14         //通过注解获取IoC容器对象
    15         ApplicationContext ctx=new  AnnotationConfigApplicationContext(ManagerScan.class);
    16         System.out.println(ctx.getBean("ds").toString());
    17     } 
    18 }

     测试结果显示:可以从Spring IoC容器中拿到ds这个Bean对象。

    7、注解自定义Bean的初始化和销毁方法:

      注解@Bean不能使用在类的标注上,它主要使用在方法上,@Bean的配置项包含4个配置项:

    • name:是一个字符串数组,允许配置多个BeanName。
    • autowire:标志是否是一个引用的Bean对象,默认值是AutoWire.No。
    • initKMethod:自定义初始化方法。
    • destoryMethod:自定义销毁方法。

    基于上面的描述,自定义初始化的方法是initMethod,销毁的方法则是destoryMethod。

    贴出测试代码:

    创建一个基本POJO类:UserBean.java (内置自定义的初始化和销毁方法

     1 package com.xfwl.spring.annotation.bean;
     2 
     3 import org.springframework.beans.factory.annotation.Value;
     4 import org.springframework.context.annotation.ComponentScan;
     5 import org.springframework.stereotype.Component;
     6 
     7 /**
     8  * 测试注解:@Component装配Bean
     9  * @author Jason
    10  * 
    11  */
    12 @Component("user")    //注入user  //@Component("user")或者@Component(value="user")
    13 public class UserBean {
    14     @Value("xfww")
    15     private String uname;
    16     @Value("123456")
    17     private String upwd;
    18     public UserBean(){}
    19     public UserBean(String uname,String upwd){
    20         this.uname=uname;
    21         this.upwd=upwd;
    22     }
    23     public String getUname() {
    24         return uname;
    25     }
    26     public void setUname(String uname) {
    27         this.uname = uname;
    28     }
    29     public String getUpwd() {
    30         return upwd;
    31     }
    32     public void setUpwd(String upwd) {
    33         this.upwd = upwd;
    34     }
    35     @Override
    36     public String toString() {
    37         return "UserBean [uname=" + uname + ", upwd=" + upwd + "]";
    38     }    
    39     /**Bean生命周期测试**/
    40     public void init(){
    41         System.out.println("【"+this.getClass().getSimpleName()+"】执行自定义初始化方法!");
    42     }
    43     public void mydestory(){
    44         System.out.println("【"+this.getClass().getSimpleName()+"】执行自定义销毁法!");
    45     }
    46 }    

     创建一个测试@Bean的类:(特别说明一下:注解@Configuration表示是告诉spring这个类是一个配置类,相当于我们的xml配置文件

     1 package com.xfwl.spring.annotation.bean;
     2 
     3 import org.springframework.beans.factory.BeanNameAware;
     4 import org.springframework.beans.factory.DisposableBean;
     5 import org.springframework.beans.factory.InitializingBean;
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.context.annotation.Bean;
     8 import org.springframework.context.annotation.ComponentScan;
     9 import org.springframework.context.annotation.Configuration;
    10 @Configuration
    11 @ComponentScan(basePackages={"com.xfwl.spring.annotation.bean"})
    12 public class ManagerScan{    
    13     @Bean(name={"tom","jack"},initMethod="init",destroyMethod="mydestory")
    14     public UserBean getUser(@Autowired UserBean user){
    15         return user;
    16     }    
    17 }

     创建一个测试类: 

     1 package com.xfwl.spring.annotation.bean;
     2 import java.util.Properties;
     3 
     4 import javax.sql.DataSource;
     5 
     6 import org.apache.commons.dbcp2.BasicDataSourceFactory;
     7 import org.springframework.context.ApplicationContext;
     8 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
     9 import org.springframework.context.annotation.Bean;
    10 import org.springframework.context.annotation.ComponentScan;
    11 import org.springframework.stereotype.Component;
    12 @Component("test")
    13 public class TestBean {
    14     public static void main(String[] args) {        
    15         //通过注解获取IoC容器对象
    16         AnnotationConfigApplicationContext ctx=new  AnnotationConfigApplicationContext(ManagerScan.class);
    17         UserBean user=(UserBean) ctx.getBean("tom");
    18         System.out.println(user.toString());
    19         ctx.close();        
    20     } 
    21 }

     测试结果:

    1 log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
    2 log4j:WARN Please initialize the log4j system properly.
    3 log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    4 【UserBean】执行自定义初始化方法!
    5 UserBean [uname=xfww, upwd=123456]
    6 【UserBean】执行自定义销毁法!
  • 相关阅读:
    在spring MVC的controller中获取ServletConfig
    支付宝移动接入报系统繁忙,參数错误等错误
    Android:控件WebView显示网页
    android WebView总结
    关于用WebView或手机浏览器打开连接问题
    Android解决Fragment多层嵌套时onActivityResult无法正确回调的问题
    Fragment嵌套Fragment时遇到的那些坑
    Android 多个Fragment嵌套导致的三大BUG
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
  • 原文地址:https://www.cnblogs.com/newwind/p/9295889.html
Copyright © 2011-2022 走看看