您的位置:首页 > 编程语言 > Java开发

Spring 4.0 基于注解(Annotation)的配置和理解

2015-02-15 16:26 701 查看
最近刚接触spring的一些东西在做一个proj,所以情绪有点高涨。。。

在这篇文章中,涉及到的不仅会是spring core中的一些Annotation,还会涉及到比如说Spring MVC,Spring Boot中的一些Annotation。只是自己这两天看spring document的理解,会比较天马行空,当然也很基础。

对于Spring来说,最重要的概念莫过于Bean,从Bean的概念出发,Spring实现它的DI/IoC,那么就从@Bean说起,here we go

大清早的,先插一点题外话。。。

Annotation OR XML

首先插入一点不相关的。虽然看到的资料都说Annotation相较于传统的XML而言更加便捷,但我个人看下来的感受是其实写很多注解也未必见得就是那么的方便,而且XML比起Annontation好像更加易于理解,又而且XML是全盘适用的,但是Annotation在某些情况下是需要借助XML的,比如如果要DI进一个第三方的class,你没办法拿到它的源码给它打个@Bean的annotation,此时你的唯一(是唯一么?)选择就是通过在XML中加入<bean>。所以,题外话的意思就是说,Annotation不错,但是XML才是根本,两者都要抓才好。

@Configuration + @Bean

@Configuration注解会告诉Spring framework说这是个配置类,在这个类中加入@Bean注解的方法,那么就@Bean方法的返回值会被识别为Spring Bean。@Configuration + @Bean的一个例子:

@Configuration 
public class BookStoreDaoConfig{ 
    @Bean 
    public UserDao userDao(){ return new UserDaoImpl();} 
    @Bean 
    public BookDao bookDao(){return new BookDaoImpl();} 
}

这样的注解等价于如下xml配置:

<bean id=”userDao” class=”bookstore.dao.UserDaoImpl”/> 
<bean id=”bookDao” class=”bookstore.dao.BookDaoImpl”/>

在写好Bean后,你就可以在后面有需要的时候自动注入了。一般比较常用的annotation会是 ->

@Autowired

使用 @Autowired 注解进行装配,只能是根据类型进行匹配。@Autowired 注解可以用于 Setter 方法、构造函数、字段,甚至普通方法,前提是方法必须有至少一个参数。@Autowired 可以用于数组和使用泛型的集合类型。然后 Spring 会将容器中所有类型符合的 Bean 注入进来。@Autowired 标注作用于 Map 类型时,如果 Map 的 key 为 String 类型,则 Spring 会将容器中所有类型符合 Map 的
value 对应的类型的 Bean 增加进来,用 Bean 的 id 或 name 作为 Map 的 key。

@Autowired 标注作用于普通方法时,会产生一个副作用,就是在容器初始化该 Bean 实例的时候就会调用该方法。当然,前提是执行了自动装配,对于不满足装配条件的情况,该方法也不会被执行。

当标注了 @Autowired 后,自动注入不能满足,则会抛出异常。我们可以给 @Autowired 标注增加一个 required=false 属性,以改变这个行为。另外,每一个类中只能有一个构造函数的 @Autowired.required() 属性为 true。否则就出问题了。如果用 @Autowired 同时标注了多个构造函数,那么,Spring 将采用贪心算法匹配构造函数 ( 构造函数最长 )。

@Autowired 还有一个作用就是,如果将其标注在 BeanFactory 类型、ApplicationContext 类型、ResourceLoader 类型、ApplicationEventPublisher 类型、MessageSource 类型上,那么 Spring 会自动注入这些实现类的实例,不需要额外的操作。

上面的叙述有点正式,因为来自引用(http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-iocannt/)

但是其实我觉得关于@Autowired最重要的一点是,Autowired自动注入的依据是byType。也就是说如果存在一个和当前属性类型一致的
Bean ( 相同类型或者子类型 ),则使用该 Bean 进行注入。byType 能够识别工厂方法,即能够识别 factory-method 的返回类型。如果存在多个类型一致的 Bean,则抛出异常。如果没有匹配的类型,则什么也不做。注意,因为它是byType注入的,所以比如你在用@Autowired对一个字段自动注入的时候,它和该字段的名字无关,如果有一个同类型的Bean被在它的factory中,那它就会被自动注入。

@Repository @Service @Controller @Component

这几个annotation都是用于将类识别为Bean,用法比较简单,只要在类上头加个注解就可以了。我觉得这里需要注意的是Bean的概念,注意正确理解并结合上面被@Bean注解的方法的概念。

@SpringBootApplication

如果说上述的Annotation都还算比较常规的话,那么Spring Boot中的注解真的让我感觉很boot。。。比如这个@SpringBootApplication:

@org.springframework.boot.autoconfigure.SpringBootApplication
@Configuration
@EnableAutoConfiguration
@ComponentScan
@Target(value={TYPE})
@Retention(value=RUNTIME)
@Documented
@Inherited
它老人家一个顶下面这么多个,当然有好有坏。好处当然就是便捷,坏处,比如说如果用SpringBootApplication注解,那就意味着你的

@Configuration
@EnableAutoConfiguration
@ComponentScan
@Target(value={TYPE})
@Retention(value=RUNTIME)
@Documented
@Inherited
这么多个注解都被加载,并且是被按照默认的方式加入到你的proj中,少了个性化配置这几个Annotation的可能。在这么多个中间,最需要注意的是@ComponentScan。
如果你使用@SpringBootApplication注解,那么也就是说你的ComponentScan是从你这个注解了的类所在的package及其子package扫瞄,那就要注意你的包以及各种Bean的位置了。

@RestController

另一个类似的例子,我也被小坑到一下下的就是这个注解了@RestController。

@org.springframework.web.bind.annotation.RestController
@Controller
@ResponseBody
@Target(value={TYPE})
@Retention(value=RUNTIME)
@Documented
为了显得in一点,我准备严格按照Restful的架构写我的网站,所以在doc中看到有这个注解的时候,就兴冲冲地把原来地@Controller都换成了@RestController,于是问题就来了。
出于Restful的思想,我在对 "/" 的request中加了个redirect -- 本来工作得好好的redirect在annotation由@Controller变成@RestController之后就无法跳转了。。。郁闷之下仔细看了下这个@RestController,发现它中间还有一个@ResponseBody,于是就明白了。。。所以那些高大上的注解们,因为它的高大上,也可能带来各种各样奇怪的问题,so be careful.

离春节越来越近了,有点想家。

By RxC
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: