Spring架构中的注释功能

来源:百度文库 编辑:神马文学网 时间:2024/10/04 03:21:25

如何使用Spring架构中的注释功能——基础篇

文章分类:Java编程

在传统Spring架构中配置POJOs的基本操作有两种:装配和依赖注入。下面的例子中装配了两个POJO,同时指定了两个对象之间的依赖关系。

例1:实现一个简单类(Main.java)

Java代码

  1. package test;   
  2.   
  3. import org.springframework.context.ApplicationContext;   
  • import org.springframework.context.support.ClassPathXmlApplicationContext;   
  •   
  • public class Main {   
  •   
  •     private BasicService service;   
  •   
  •     public BasicService getService() {   
  •         return service;   
  •     }   
  •   
  •     public void setService(BasicService service) {   
  •         this.service = service;   
  •     }   
  •   
  •     public void print() {   
  •        service.print();   
  •     }   
  •   
  •     public static void main(String[] args) {   
  •   
  •         String[] locations = { "beans.xml" };   
  •         ApplicationContext ctx =   
  •             new ClassPathXmlApplicationContext(locations);   
  •   
  •         Main main = (Main)ctx.getBean("main");   
  •         main.print();   
  •     }   
  • }  
  • package test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class Main {private BasicService service;public BasicService getService() {return service;}public void setService(BasicService service) {this.service = service;}public void print() {service.print();}public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main = (Main)ctx.getBean("main");main.print();}}

     

     例2:基本服务类(BasicService.java)

    Java代码

    1. package test;   
    2.   
    3. public class BasicService {   
    4.   
    5.     public void print() {   
    6.         System.out.println("success");   
    7.     }   
    8. }  
    package test;public class BasicService {public void print() {System.out.println("success");}}

     例3:在配置文件中的声明(beans.xml)

    Java代码

    1. "1.0" encoding="UTF-8" ?>   
    2. "http://www.w3.org/2001/XMLSchema-instance"  
    3.     xmlns="http://www.springframework.org/schema/beans"  
    4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">   
    5.   
    6.     "main" class="test.Main">   
    7.         "service">   
    8.             "service" />   
    9.            
    10.        
    11.     "service" class="test.BasicService">   
    12.   
     对于传统装配方式而言,最大的问题在于规模逐渐变大的项目中将会有越来越多的POJOs需要在XML文件中设置。这样一方面无法迅速定位指定的对象,另一方面难于掌握对象之间的依赖关系。得益于Java5.0的注释功能,到Spring2.5之后,其架构中提供了一系列注释,用于简化装配POJOs的过程。这种方式大大降低了传统XML配置文件的管理成本,让我们来看一下将上面的例子修改成注释方式的样子。

    例4:注释版Main.java

    Java代码

    1. package test;   
    2.   
    3. import org.springframework.beans.factory.annotation.Autowired;   
  • import org.springframework.context.ApplicationContext;   
  • import org.springframework.context.support.ClassPathXmlApplicationContext;   
  • import org.springframework.stereotype.Component;   
  •   
  • @Component  
  • public class Main {   
  •   
  •     @Autowired  
  •     private BasicService service;   
  •   
  •     public void print() {   
  •         service.print();   
  •     }   
  •   
  •     public static void main(String[] args) {   
  •   
  •         String[] locations = { "beans.xml" };   
  •         ApplicationContext ctx =   
  •             new ClassPathXmlApplicationContext(locations);   
  •   
  •         Main main = (Main) ctx.getBean("main");   
  •         main.print();   
  •     }   
  • }  
  • package test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;@Componentpublic class Main {@Autowiredprivate BasicService service;public void print() {service.print();}public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main = (Main) ctx.getBean("main");main.print();}}

     例5:注释版BasicService.java

    Java代码

    1. package test;   
    2.   
    3. import org.springframework.stereotype.Component;   
    4.   
    5. @Component("service")   
    6. public class BasicService {   
    7.   
    8.     public void print() {   
    9.         System.out.println("success");   
    10.     }   
    11. }  
    package test;import org.springframework.stereotype.Component;@Component("service")public class BasicService {public void print() {System.out.println("success");}}

     例6:注释版beans.xml

    Java代码

    1. "1.0" encoding="UTF-8" ?>   
    2. "http://www.w3.org/2001/XMLSchema-instance"  
    3.     xmlns="http://www.springframework.org/schema/beans"  
    4.     xmlns:context="http://www.springframework.org/schema/context"  
    5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">   
    6.   
    7.     package="test">   
    8.        
    9.   
     对于Spring架构中的注释功能而言,我们需要掌握哪些要点呢?

     

    @Component

    所有的Spring注释中最重要的莫过于@Component,其作用就是在Spring容器中装配一个POJO对象。@Component作用于类声明之前,其用法有两种:

    @Component
    @Component(“Spring容器内的对象名”)

    第一种注释方法会在Spring容器中实例化一个以类名的首字母为小写命名的POJO对象。如例4中对Main类的注释将会在Spring容器中实例化一个名为main的POJO对象:

    Java代码

    1. package test;   
    2. ...   
    3.   
    4. @Component  
  • public class Main {   
  •     ...   
  •   
  •     public static void main(String[] args) {   
  •   
  •         String[] locations = { "beans.xml" };   
  •         ApplicationContext ctx =   
  •             new ClassPathXmlApplicationContext(locations);   
  •   
  •         Main main = (Main)ctx.getBean("main");   
  •         main.print();   
  •     }   
  • }  
  • package test;...@Componentpublic class Main {...public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main = (Main)ctx.getBean("main");main.print();}}

     当然,如果不满意类名首字母小写的命名规则,第二种注释方法允许我们自定义POJO的名称。如例5中对BasicService的注释:

    Java代码

    1. package test;   
    2. ...   
    3.   
    4. @Component("service")   
    5. public class BasicService {   
    6.     ...   
    7. }  
    package test;...@Component("service")public class BasicService {...}
     通常情况下保存在Spring容器中的POJOs有两种形态:singleton与prototype。@Component与@Scope配合即可指定不同的形态。@Scope紧随@Component之后,其用法如下:

    @Scope(“singleton”)
    @Scope(“prototype”)

    我们可以用下面的例子测试prototype或singleton形态的POJOs:

    Java代码

    1. package test;   
    2.   
    3. import org.springframework.context.ApplicationContext;   
    4. import org.springframework.context.annotation.Scope;   
    5. import org.springframework.context.support.ClassPathXmlApplicationContext;   
    6. import org.springframework.stereotype.Component;   
    7.   
    8. @Component  
    9. @Scope("prototype")   
    10. public class Main {   
    11.   
    12.     public void print() {   
    13.         System.out.println(toString());   
    14.     }   
    15.   
    16.     public static void main(String[] args) {   
    17.   
    18.         String[] locations = { "beans.xml" };   
    19.         ApplicationContext ctx =   
    20.             new ClassPathXmlApplicationContext(locations);   
    21.   
    22.         Main main1 = (Main) ctx.getBean("main");   
    23.         main1.print();   
    24.   
    25.         Main main2 = (Main) ctx.getBean("main");   
    26.         main2.print();   
    27.   
    28.         System.out.println(main1 != main2);   
    29.     }   
    30. }  
    package test;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.Scope;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.stereotype.Component;@Component@Scope("prototype")public class Main {public void print() {System.out.println(toString());}public static void main(String[] args) {String[] locations = { "beans.xml" };ApplicationContext ctx =new ClassPathXmlApplicationContext(locations);Main main1 = (Main) ctx.getBean("main");main1.print();Main main2 = (Main) ctx.getBean("main");main2.print();System.out.println(main1 != main2);}}
     

    @Autowired

    与@Component对应,@Autowired用于Spring容器中POJOs之间的依赖注入操作,使用该注释的最大好处是不必提供传统JavaBeans的setter方法。如例4与例1相比,私有的成员变量service没有提供settter方法,仅靠@Autowired就可以注入与之对应的service对象。@Autowired作用于类的成员变量、类的setter方法或类的构造函数。其用法有以下两种:

    @Autowired
    @Autowired(required = false)

    独立的@Autowired以byType方式进行依赖注入。如例4中对service成员变量的注释:

    Java代码

    1. package test;   
    2. ...   
    3.   
    4. @Component  
    5. public class Main {   
    6.   
    7.     @Autowired  
    8.     private BasicService service;   
    9.   
    10.     ...   
    11. }  
    package test;...@Componentpublic class Main {@Autowiredprivate BasicService service;...}

     只要在Spring容器中存在一个(只有一个)类型为test.BasicService的POJO时,byType方式就可以正确注入。否则将抛出异常,如果不希望强制注入不存在的对象,可以使用第二种方式进行注释。如:

    Java代码

    1. package test;   
    2. ...   
    3.   
    4. @Component  
    5. public class Main {   
    6.   
    7.     @Autowired(required = false)   
    8.     private BasicService service;   
    9.   
    10.     ...   
    11. }  
    package test;...@Componentpublic class Main {@Autowired(required = false)private BasicService service;...}
     当Spring容器中不存在相同类型的POJO对象时,成员变量service将不进行依赖注入操作。但是如果Spring容器中存在多个相同类型但名字不同的POJOs时,又该如何处理呢?

    @Autowired与@Qualifier配合使用时将会以byName方式进行依赖注入。以byName方式进行依赖注入正是为了避免相同类型的不同POJOs在注入时发生冲突。@Qualifier作用于类的成员变量、类的setter方法中的参数或类的构造函数中的参数,@Qualifier的用法如下:

    @Qualifier(“Spring容器内的对象名”)

    如将例4的内容修改一下。如下例:

    Java代码

    1. package test;   
    2. ...   
    3.   
    4. @Component  
    5. public class Main {   
    6.   
    7.     private BasicService service;   
    8.   
    9.     @Autowired  
    10.     public Main(@Qualifier("basicService")BasicService service) {   
    11.         this.service = service;   
    12.     }   
    13.   
    14.     ...   
    15. }  
    package test;...@Componentpublic class Main {private BasicService service;@Autowiredpublic Main(@Qualifier("basicService")BasicService service) {this.service = service;}...}
     此时的成员变量只会从Spring容器中查找名字为service的POJO进行注入。当然如果定位到的POJO类型不符合要求或者相同名字的POJO在Spring容器中不存在,上述方法仍然会抛出异常。此时如有必要就需要@Autowired(required=false)来帮忙了。package test;Java代码
    1. ...   
    2.   
    3. @Component  
    4. public class Main {   
    5.   
    6.     private BasicService service;   
    7.   
    8.     @Autowired  
    9.     public Main(@Qualifier("basicService")BasicService service) {   
    10.         this.service = service;   
    11.     }   
    12.   
    13.     ...   
    14. }  
    ...@Componentpublic class Main {private BasicService service;@Autowiredpublic Main(@Qualifier("basicService")BasicService service) {this.service = service;}...}
     

    与成员变量的依赖注入功能相似,@Autowired同样可以通过构造函数或setter方法进行注入。如:

    Java代码

    1. package test;   
    2. ...   
    3.   
    4. @Component  
    5. public class Main {   
    6.   
    7.     private BasicService service;   
    8.   
    9.     @Autowired  
    10.     public Main(@Qualifier("basicService")BasicService service) {   
    11.         this.service = service;   
    12.     }   
    13.   
    14.     ...   
    15. }  
    package test;...@Componentpublic class Main {private BasicService service;@Autowiredpublic Main(@Qualifier("basicService")BasicService service) {this.service = service;}...}
     

    上述代码中指明了在构造函数中进行依赖注入,同时指定参数service只接收名字为basicService的POJO。

    XML配置文件中的设置

    为了使用Spring架构中的注释功能,例6所示的内容是最小的配置要求。请注意XML根标签属性中与传统Spring配置文件的不同:

    传统配置文件

    Java代码

    1. "1.0" encoding="UTF-8" ?>   
    2. "http://www.w3.org/2001/XMLSchema-instance"  
    3.     xmlns="http://www.springframework.org/schema/beans"  
    4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">   
    5.   
    6.     "main" class="test.Main">   
    7.         "service">   
    8.             "service" />   
    9.            
    10.        
    11.     "service" class="test.BasicService">   
    12.   

     注释用配置文件

    Java代码

    1. "1.0" encoding="UTF-8" ?>   
    2. "http://www.w3.org/2001/XMLSchema-instance"  
    3.     xmlns="http://www.springframework.org/schema/beans"  
    4.     xmlns:context="http://www.springframework.org/schema/context"  
    5.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">   
    6.   
    7.     package="test">   
    8.        
    9.   
     与传统Spring配置文件相比,最大的不同在于配置文件中不必使用bean标签来装配已经使用了注释的POJOs,配置文件的内容将变得简洁明了。

    其中标签的作用有两点:
    1. 允许使用Spring架构中的所有注释功能,包括上述所有注释;
    2. 指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。

    总之,Spring2.5的注释功能可以极大的提高开发效率,使大量的维护工作得以简化。我们没有理由不掌握这样的技术!