spring3.0使用annotation完全代替XML

@Service与@Component有什么不同?那天被问到这个问题,一时之间却想不起来,就利用这篇文章来纪录spring3.0中常用的annotation。

从spring2.5开始,annotation结合BeanPostProcessor成了扩展Spring IoC容器的常用方法。Spring2.5增加了对JSR-250中@Resource, @PostConstruct, @PreDestroy的支持,Spring 3.0又增加了对JSR-330 (Dependency Injection for Java)中 @Inject,@Qualifier, @Named, @Provider的支持。将相关的jsr jar包丢到classpath,并注册相应的BeanPostProcessor,其它的一切spring会帮你完成。spring还提供了一个简便的 方法,通过在context的XML配置文件中加入:

Xml代码   收藏代码
  1. < context:annotation-config />   


spring 会自动注册AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, RequiredAnnotationBeanPostProcessor,代码中就可以使用@Autowired, @Required等annotaion了。

再回到文章开头的问题吧。spring从2.5开始加入了classpath scanning的功能,来代替之前在xml中定义Bean。首先在context的XML配置文件中加入:

Xml代码   收藏代码
  1. < context:component-scan   base-package = "org.example" />   


spring 便会在org.example以及它的子package中查找所有的类,将符合条件的Bean注册在IoC容器当中。到3.0,spring引入了4种原 型annotation(stereotype annotaion),分别为@Component, @Serivce, @Controller, @Repository。一般情况下只在将类加上@Componet,spring在扫描classpath的时候会自动检测到,并将这个类注册到IoC 容器中,在代码的其它部分,便可以借助@Autowired来注入这个Bean。后面的三种原型分别是特殊的@Conponet,适用于更加特殊的场合, 比如Service层,Spring MVC, DAO等。这一点从源码上也可以看出:

Java代码   收藏代码
  1. @Target ({ElementType.TYPE})  
  2. @Retention (RetentionPolicy.RUNTIME)  
  3. @Documented   
  4. @Component   
  5. public   @interface  Service {  
  6.     String value() default   "" ;  
  7. }  
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
	String value() default "";
}



@Service本身就是被@Componet这个元注解(meta annotaion)标注的。因此对于这三个层的Bean, spring的文档也推荐将它们标注为@Service, @Controller与@Repository,因为这样更方便其它工具对这些特殊Bean的处理以及为它们加上相关AOP的 aspects,spring在后续版本的升级上也可能对它们增加更多的特殊语义。至于它们到底比普通的@Componet多了哪些 aspects,spring的文档上并没有详细说明,只简单地提到了对于@Repository,spring会自动加上exception translation,用于转化持久层抛出的异常。我google了一下,包括spring论坛的帖子 ,也没能找到这方面的详细信息,这点希望熟悉spring源代码的朋友能够说说。

现在通过classpath scanning以及@Component,@Autowired等annotation,我们已无须通过xml来定义Bean了。但还必须在 application context的xml中添加<context:annotation-config/>与<context:component- scan base-package="org.example"/>。再进一步想,能不能把这个配置文件也去掉,实现真正的零配置?spring3.0原先 Spring JavaConfig项目的功能移到了Spring Core里面,从而实现了利用Java代码来代替传统的XML配置文件,这个功能是通过@Configuration, @Bean, @Import, @DependsOn等annotation实现的。

Java代码   收藏代码
  1. @Configuration   
  2. public   class  AppConfig {  
  3.     @Bean   
  4.     public  GreetingDao greetingDao() {  
  5.         return   new  GreetingDao();  
  6.     }  
  7. }  
  8.   
  9. public   class  GreetingDao {  
  10.     public  String getGreeting(){  
  11.         return   "Hi" ;  
  12.     }  
  13. }  
@Configuration
public class AppConfig {
    @Bean
    public GreetingDao greetingDao() {
        return new GreetingDao();
    }
}

public class GreetingDao {
	public String getGreeting(){
		return "Hi";
	}
}



@configuration表明这个类包含Bean的定义,@Bean在这里就相当于原先的配置:<bean id="greetingDao" class="septem.demo.GreetingDao"/>。通过 AnnotationConfigApplicationContext就可以使用这个Bean了:

Java代码   收藏代码
  1. @Test   
  2.     public   void  test_java_config(){  
  3.         AnnotationConfigApplicationContext ctx = new  AnnotationConfigApplicationContext(AppConfig. class );  
  4.         GreetingDao dao = ctx.getBean(GreetingDao.class );  
  5.         assertEquals("Hi" , dao.getGreeting());  
  6.     }  
@Test
	public void test_java_config(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
		GreetingDao dao = ctx.getBean(GreetingDao.class);
		assertEquals("Hi", dao.getGreeting());
	}



注意AppConfig里面的greetingDao虽然是是直接new出来的,但它的默认scope仍是singleton,跟采用配置文件的 情况是一样的,如果需要prototype,则可以另外为它加上@Scope("prototype")。上面采用的方法是手工将Bean定义在 @Configuration里面,我们同样可以让spring自动检测Bean,比如下面的GreetingSerivce:

Java代码   收藏代码
  1. @Service   
  2. public   class  GreetingService {  
  3.     public  String sayHello(){  
  4.         return   "Hello" ;  
  5.     }  
  6. }  
@Service
public class GreetingService {
	public String sayHello(){
		return "Hello";
	}
}



将GreetingService标注为@Service,就不需要在AppConfig里面注册了:

Java代码   收藏代码
  1. @Test    
  2.     public   void  test_service(){  
  3.         AnnotationConfigApplicationContext ctx = new  AnnotationConfigApplicationContext();  
  4.         ctx.scan("septem.demo" );  
  5.         ctx.refresh();  
  6.   
  7.         GreetingService service = ctx.getBean(GreetingService.class );  
  8.         assertEquals("Hello" , service.sayHello());  
  9.     }  
@Test 
	public void test_service(){
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
		ctx.scan("septem.demo");
	    ctx.refresh();

		GreetingService service = ctx.getBean(GreetingService.class);
		assertEquals("Hello", service.sayHello());
	}



以上的ctx.scan("septem.demo")就相当于配置文件:<context:component-scan base-package="septem.demo"/>。注意因为@Configuration本身也是被@Component这个meta- annotation标注的,所以AppConfig也不需要手工在 AnnotationConfigApplicationContext里注册,它同@Service一样会被自动检测到。Spring3.0还提供了 AnnotationConfigWebApplicationContext用来代替原先web项目中的 XmlWebApplicationContext,这样在web项目中同样可以实现真正的零配置了。Spring的官方文档 还提供了针对更复杂情况的处理方法,有兴趣的朋友可以看看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值