近来发现把写博客当成任务了。呵呵,调整下了下心态:我在这里写,只是希望你看到,能有所帮助。

spring注解的发展史

在spring2.5的官方指导里指出,spring从2.0开始引入了一些用于配置的annotation, 包括 @Transactional, @Required and @PersistenceContext/@PersistenceUnit.

然而我在一篇文章里,看到spring注解从1.2开始便有了,于是我不得不回头去查阅了下spring相关文档。得出如下结论:

1. spring1.0: 从1.0开始就在对元数据问题出谋划策,没有正式引入注解。但有了SOURCE级别的元数据支持

2. spring1.2: 在1.2的时候是java1.5的发布,并且面对要兼容1.3,1.4版本的问题,但已经有了基于java5.0的注解如: @ManagedResource,基本无关注。 aspectJ 在该版本中仍在建设过程中,还停留在aspect。

3. spring2.0 :有了比较多的注解,包括AspectJ已经采用了注解方法,并且支持xml配置

4. spring2.5: 引入了用于配置的完整的Annotation集合: @Autowired,以及对JSR-250注解@Resource, @PostConstruct and @PreDestroy的支持

5. spring3.0: 注解已经非常的丰富,spring的 JavaConfig项目已经加入到spring框架中,这意味着将直接支持如@Configuration,@Bean,@Value等标签

6. spring3.1: 对@Configuration有所增强,充实。 

认识注解:

我相信大家接触注解(annotation),最早应该是@Override,@Deprecated,@Suppress Warnings,就算接触不多,也没关系,我这里尽量系统的说一遍。

1. 注解:也被叫做 元数据(其实我觉得更是元数据的一种表现形式),为代码添加信息提供了一种形式化的方法,在稍后的某个时候用到这些数据

2. 元数据: 用于描述数据的数据(MetaDate),翻译成信息的信息会跟更好理解,举例来说:我这边文章就是一些数据,或者信息,而对这个文章的标题,时间,关键字,都可以称为元数据

3. 注解是元数据与源代码结合在一起,但不保存在外部文档(如xml)的趋势下催生的

阴暗的说,其实你知道上面这些也没大用,反正能写能用就成,下面介绍注解的格式 

注解的格式

注意: 注解本身不做任何事

注解可以与其他任何修饰符共同作用于方法,例如public,static或者void。从语法角度看,注解的使用方式与修饰符使用几乎一模一样。

为何说几乎,举例:

有方法:

  public void create(int i){}
和 注解
  @Test, @Test1

可以如下写法:

1.

  1. @Test  
  2. public void create(int i){} 

2.

  1. public @Test void create(int i){}  
  1. @Test public void create(int i){}   
  2. //注意不能放在void的后面 

3.

  1. public void create(@Test int i){}  

4.

  1. @Test@Test1  
  2. public void create(int i){}  
  3. //注解以@分隔,与空白符包括行(row) 无关 

 java中自定义一个注解和应用:

只举一个简单例子,算是入门。但对你理解spring注解将会是个不错的过渡,至少你能感觉到,注解原来这么简单。

例子:

  1. import java.lang.annotation.*;   
  2. @Target(ElementType.METHOD)//注解只能用于方法   
  3. @Retention(RetentionPolicy.RUNTIME)//注解在运行期也保留,可以通过反射读取注解信息   
  4. public @interface Scholar {   
  5.     public int id();   
  6.     public String descrition() default "no description";   
  7. }  
  8.  

建立一个类TestScholar 来应用@Scholar

代码:

  1. //@Scholar(id=1)//Scholar只能用于方法
  2. public class TestScholar {   
  3.     @Scholar(id=1)   
  4.     public void test() {};   

  效果图:
p_w_picpath
通过上面的例子,对注解算是有些认识。注意:
1. @Target如果你是第一次接触,不要急,下面有讲解
2. 你需要注意 注解的方式很像接口字段定义需要加小括号
3. 注解可以有缺省,如果缺省(default),则可以不赋值

元注解

记得元数据的解释吗?是的,元注解专职负责注解其他注解 

元注解

参数

说明

@Target

  表示注解可用于什么地方
  CONSTRUCTOR 构造器的声明
  FIELD 域声明(包括enum实例)
  LOCAL_VARIABLE 局部变量声明
  METHOD 方法声明
  PACKAGE 包声明
  PARAMETER 参数声明
  TYPE 类,接口(包括注解)或者enum声明

@Retention

 

表示需要什么级别保存该注解信息

  SOURCE 注解将被编译器丢弃
  CLASS 注解在class文件中可用,会被VM丢弃
  RUNTIME VM在运行期被保留,可以通过反射机制读取注解

@Documented

 

将此注解包含在Javadoc中

@Inherited

 

允许子类集成父类中的注解

 注解类型

所有基本类型(int,float,boolean等)
String

Class
enum
Annotation
以上类型的数组

 

读取注解的内容:

通过反射机制,都会有getAnnotation()方法

如方法(Method)的: 

  1. for(Method m : of.getDeclaredMethods())  
  2. Scholar scholar = m.getAnnotation(Scholar.class)  

如果是初学,可能要去专门学习下,呵呵,这里只是为了给spring做个入门。


spring2.5 注解

spring2.5算是一个里程碑的版本,而注解2个比较大的改革便是:
1. Annotation驱动的bean配置
2. 对Spring MVC的支持

分别讲解一下:

1.Annotation驱动的bean配置

1.1 基于注解(Annotation-based)的配置

要使注解可用,您必须使用 Java 5 (Tiger)或更新的版本,以使得可以访问源代码层次的注解。这些注解可以被注册为独立 bean 的定义,但它们也可以被隐式地注册,通过基于 XML 的配置方式,如下例(请注意包含 'context' 命名空间):

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans   
  6.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
  7.            http://www.springframework.org/schema/context  
  8.            http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 
  9. <context:annotation-config/>     
  10.   <!--注意:xmlns:context="http://www.springframework.org/schema/context" -->        
  11.   <!--(隐式注册 post-processors 包括了
  12. AutowiredAnnotationBeanPostProcessor
  13. CommonAnnotationBeanPostProcessor
  14. PersistenceAnnotationBeanPostProcessor也包括了前面提到的 RequiredAnnotationBeanPostProcessor。) -->
  15. </beans> 

1.2 @Autowired

引用些官方例子:

1)@Autowired 注解可以用于“传统的”setter 方法,如下例:

  1. public class SimpleMovieLister {  
  2.     private MovieFinder movieFinder;  
  3.     @Autowired  
  4.     public void setMovieFinder(MovieFinder movieFinder) {  
  5.         this.movieFinder = movieFinder;  
  6.     }  
  7.     // ...  

2)这个注解也可以用于以属性为参数/多个参数的方法

  1. public class MovieRecommender {  
  2.     private MovieCatalog movieCatalog;  
  3.     private CustomerPreferenceDao customerPreferenceDao;  
  4.  
  5.     @Autowired  
  6.     public void prepare(MovieCatalog movieCatalog,  
  7.             CustomerPreferenceDao customerPreferenceDao) {  
  8.         this.movieCatalog = movieCatalog;  
  9.         this.customerPreferenceDao = customerPreferenceDao;  
  10.     } 
  11. // ...  

3@Autowired注解甚至可以用于构造器与字段:

  1. public class MovieRecommender {  
  2.     @Autowired  
  3.     private MovieCatalog movieCatalog;  
  4.     private CustomerPreferenceDao customerPreferenceDao;  
  5.     @Autowired  
  6.     public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {  
  7.         this.customerPreferenceDao = customerPreferenceDao;  
  8.     } 
  9. // ...  

4)也可以一种提供来自ApplicationContext的特殊类型的所有 beans,注解字段或者方法,例如:

  1. public class MovieRecommender {  
  2.     @Autowired  
  3.     private MovieCatalog[] movieCatalogs;   
  4.     // ...  

5)这同样适用于集合类型:

  1. public class MovieRecommender {  
  2.     private Set<MovieCatalog> movieCatalogs;  
  3.  
  4.     @Autowired  
  5.     public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {  
  6.         this.movieCatalogs = movieCatalogs;  
  7.     }   
  8.     // ...  
  9. }  

注意:在缺省情况下,当出现0个候选的 beans时自动连接将失败;缺省行为把连接方法,构造器,字段假设为 required 的依赖。这样的行为如下所示:

  1. public class SimpleMovieLister {  
  2.     private MovieFinder movieFinder;  
  3.  
  4.     @Autowired(required = false)  
  5.     public void setMovieFinder(MovieFinder movieFinder) {  
  6.         this.movieFinder = movieFinder;  
  7.     }   
  8.     // ...  
  9. }  

1.3 基于注解的微调

1)有多个实例,需要筛选出一个,可以通过Qualifier注解

  1. public class MovieRecommender {  
  2.     @Autowired  
  3.     @Qualifier("mainCatalog")  
  4.     private MovieCatalog movieCatalog;   
  5.     // ...  

2)@Qualifier注解也能够被指定为构造器的参数或者方法的参数:

  1. public class MovieRecommender {  
  2.     private MovieCatalog movieCatalog;  
  3.     private CustomerPreferenceDao customerPreferenceDao;  
  4.  
  5.     @Autowired  
  6.     public void prepare(@Qualifier("mainCatalog") MovieCatalog movieCatalog,  
  7.             CustomerPreferenceDao customerPreferenceDao) {  
  8.         this.movieCatalog = movieCatalog;  
  9.         this.customerPreferenceDao = customerPreferenceDao;  
  10.     }   
  11.     // ...  

2.对Spring MVC的支持

Spring 2.5 为MVC 控制器引入了一种基于Annotation(注解)的编程模型, 使用@RequestMapping, @RequestParam, @ModelAttribute等等注解。 

1.要实现控制器@Controller自动探测

加入配置

  1. <!--package是要扫描的包-->
  2. <context:component-scan base-package="org.springframework.samples.petclinic.web"/> 

2.一个实例

  1. @Controller  
  2. @RequestMapping("/editPet.do")  
  3. @SessionAttributes("pet")  
  4. public class EditPetForm {  
  5.     private final Clinic clinic;  
  6.  
  7.     @Autowired  
  8.     public EditPetForm(Clinic clinic) {  
  9.         this.clinic = clinic;  
  10.     }  
  11.  
  12.     @ModelAttribute("types")  
  13.     public Collection<PetType> populatePetTypes() {  
  14.         return this.clinic.getPetTypes();  
  15.     }  
  16.  
  17.     @RequestMapping(method = RequestMethod.GET)  
  18.     public String setupForm(@RequestParam("petId") int petId, ModelMap model) {  
  19.         Pet pet = this.clinic.loadPet(petId);  
  20.         model.addAttribute("pet", pet);  
  21.         return "petForm";  
  22.     }  
  23.  
  24.     @RequestMapping(method = RequestMethod.POST)  
  25.     public String processSubmit(@ModelAttribute("pet") Pet pet,  
  26.             BindingResult result, SessionStatus status) {  
  27.         new PetValidator().validate(pet, result);  
  28.         if (result.hasErrors()) {  
  29.             return "petForm";  
  30.         } else {  
  31.             this.clinic.storePet(pet);  
  32.             status.setComplete();  
  33.             return "redirect:owner.do?ownerId=" + pet.getOwner().getId();  
  34.         }  
  35.     }  

spring2.5 对注解的2个主要关注点已经阐述,但是随着注解的大量应用,spring可能融入一些其他的框架,如AspectJ ,都会有自己的注解,需要大家了解并且注意,但是他并不是与spring-framework实际相关。

收尾

我想这些东西,很多人都应该写过,这里就不反复阐述。我写文章的目的,是为spring3新特征和加强(包括注解)做铺垫,有时间就写写。