Spring IoC学习笔记(1):注解配置Bean
来源:互联网 发布:魔兽世界数据库1.11 编辑:程序博客网 时间:2024/06/06 14:36
之前用到Spring AOP,于是就总结了一下,Spring的另一个特点也顺便总结一下(其实是我的强迫症犯了)。
大家最开始学习Spring时,基本上都是先学XML的配置方式,但是在实际的开发中反倒是基于注解的方式使用的更多一些(个人感觉,不喜轻喷)。所以首先总结一下Bean的基于注解的配置方式。
一、 组件扫描机制
- @Component:最普通的组件,说明它能被Spring容器管理,其他的组件都是通过加入相应的具体含义在它的基础上扩展而来;
- @Controller:标识表现层的组件;
- @Service:标识服务层的组件;
- @Repository:标识持久层的组件;
可以使用的组件当然不止以上区区几种,可以说,只要是任何被@Component或者由它标识的注解标识的注解(好绕啊!!)都可以被Spring的容器管理,如使用@RestController,该注解就是被@Controller和@ResponseBody标识。看源码如下:
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Controller@ResponseBodypublic @interface RestController {/** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any * @since 4.0.1 */String value() default "";}而上面所说的@Controller,@Service,@Repository都是被@Component标识,看源码如下:
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Controller {/** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any */String value() default "";}//...@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Service {/** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any */String value() default "";}//...@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Repository {/** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any */String value() default "";}
综上所述,我们自己也可以自定义注解被Spring的IoC容器检测(好开心,有没有??),还有一个问题就是其实上面各种注解之间在被Spring扫描识别时,被没有任何区别,也就是可以互换使用,但是不建议这样做(毕竟人家不想那么土嘛),还是建立大家在合适的环境中使用对应的注解,并且Spring已经开始识别这几个注解了,首先就是@Repository在持久层中,已经开始作为自动异常转换的标识了,所以大家小心了。
对于扫描到的组件,我们可以通过该相应的名称在容器中获得该组件,和XML配置中的bean的id相对应,我们有两种手段处理:
- 通过上面注解源码中value属性标识,该值默认为空字符串;
- Springl有自己的默认命名策略,使用非限定类名(就是不带包名,说的这么高大上干嘛),第一个字母小写,例如你的类是UserService,所以你可以通过userService这个名称在容器找到对应的组件;
建议还是使用value属性来标识一下吧,毕竟默认策略里面究竟是怎么实现的,我们可能不太清楚(是我们不想清楚好吧。。。),这样百分百不会出错。
加好注解就结束了吗,骚年,还太年轻!学习Spring怎么不知道下面这条呢!
<context:component-scan base-package="..." />
我一直弄不懂这个配置到底做了什么事情,所以查了一下官方文档,发现通过它,可以注册几个Bean,其中还有几个关于它和另外一个配置的区别(你懂得),之后会另写一篇总结一下,这里就先不说了。
在这个配置信息中还可以使用许多的过滤器(自己命名的),base-package用来说明扫描哪些包及其子包,必须使用全限定名,在其中还可以指定多个包,包名之间使用逗号、分号或者空白分隔。
另外该节点下还有如下子节点:
- <context:include-filter>:表示要包括哪些目标类;
- <context:exclude-filter>:表示要排除哪些目标类;
这两种子节点可以同时有多个来配置不同的过滤器,这两个节点的属性也是相同的,都有type和expression属性,关于type,Spring提供了几种过滤器的类型,不过常用的只有一两种:
- annotation:用在目标组件上的注解来进行过滤;
- regex:用正则表达式匹配全限定类名;
- 其他:assignable,aspectj,custom,如果想进一步了解,请查官方文档;
下面给出一个官方的示例:
<context:component-scan base-package="org.example"> <context:include-filter type="regex" expression=".*Stub.*Repository"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/></context:component-scan>
注意在使用<context:include-filter>时,如果只想扫描被特定注解指定的类,但是由于默认情况下Spring会扫描对应路径下所有带有上述四个注解的类,所以要改变这种默认行为,通过使用use-default-filters属性来实现,它默认是true,如果有需要可以改为false,例如修改上述例子:
<context:component-scan base-package="org.example" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/></context:component-scan>这样上述的配置只会扫描被注解@Repository标识的类,不会扫描其他三个注解标识的类。
二、 组件装配机制
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Autowired {/** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */boolean required() default true;}从中可以看出,这个注解几乎可以使用在任何地方,但是使用最多的应该是字段和方法上(纯属个人观点),它还有一个属性required,这是说明在使用这个注解之后是否一定要提供相应的实例化对象,默认=为true,说明一定要提供,如果没有则会报错,看下面实例:
@Servicepublic class UserService {@Autowiredprivate UserRepository repository;public void execute(){System.out.println(repository);}}
@Repositorypublic class UserRepository {}下面是测试代码:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService service = (UserService) context.getBean("userService");service.execute();当没有在IoC容器中提供UserRepository的实例时,报如下的错误:
- 默认方式,Spring通过名称自动识别,一般我自己不用,感觉莫名其妙的总会出现一些问题,如果大家有想深入了解的可以看看源码,如果名字识别错误会出现如下错误;
- 通过使用@Qualifier来标识相关联的Bean的名称,关于这个,如果正确配置就一定不会出问题,下面给出一个例子;
@Servicepublic class UserService {@Autowired@Qualifier("user2Repository")private UserRepository repository;public void execute(){System.out.println(repository);}}将UserRepository改成接口,并提供两个实现类,如下:
public interface UserRepository {}//...@Repositorypublic class User1Repository implements UserRepository {}//...@Repositorypublic class User2Repository implements UserRepository {}如果没有使用@Qualifier,则会出现和使用默认识别行为一样的错误,另外该注解还可以和在组件扫面中说的四个注解中的value属性配合使用,现在输出如下:
顺便说一下,当组件扫描或者组件装配涉及到接口时,只要在该接口的实现类上加入对应的注解就可以。
相关的内容可以看下面的相关文章。
- Spring @Resource、@Autowired、@Qualifier的注解注入及区别
- javax.inject中@Inject、@Named、@Qualifier和@Provider用法
- Spring IoC学习笔记(1):注解配置Bean
- Spring学习(九)使用ioc注解方式配置bean
- Spring学习(九)使用ioc注解方式配置bean
- spring学习笔记----通过注解配置Bean(1)
- Spring学习笔记之通过注解配置Bean(1)
- Spring学习笔记----注解方式配置bean
- spring学习笔记----通过注解配置Bean(2)
- spring学习基础(ioc底层原理,bean的配置和注解)
- Spring学习笔记---2.1-IOC容器解析Bean配置信息
- Spring-IOC装配Bean(注解方式)
- spring学习总结(八):IOC & DI 配置Bean之注解配置
- Spring IoC学习笔记(2):初步配置bean以及一般操作
- Spring学习笔记三: 通过注解配置Bean
- Spring学习笔记之通过注解配置Bean
- Spring学习笔记之通过注解配置Bean(2)
- Spring学习笔记(二) IoC容器与Bean
- Spring学习笔记(3.IOC及Bean容器)
- spring Ioc的bean的学习笔记
- 快速Android开发系列网络篇之Retrofit
- 学习函数模板,意外学习sizeof
- 路由器桥接(WDS) 无法从副路由(B路由,从路由)上网 解决方法(DHCP设置)
- IO流的作业题
- 8 次尝试,带你走进 iOS 精益编程--cocoaChina
- Spring IoC学习笔记(1):注解配置Bean
- C#中实现并发的几种方法以及其性能测试
- Nginx+php fastcgi 发生 Access Denied
- todo:关于Delphi的几个问题
- android 消息机制
- Java基础之理解Annotation
- centos7下安装composer
- PHP: fopen() Permission denied
- 【文件】一开始学的就不好