Spring(16)——使用注解进行bean定义
16 使用注解进行bean定义
除了在Spring配置文件中通过bean元素定义一个bean外。我们还可以通过在Class上使用特定的注解进行标注,然后让Spring去扫描这些特定的注解,并把它们当做一个bean进行定义。
16.1 @Component
@Component是Spring中用来定义bean最基本的注解,通过在Class类上标注对应的注解就可以让Spring扫描到对应的定义,并把其作为一个bean定义到对应的bean容器中。
@Component public class Hello {}
当Spring扫描到这样一个使用@Component进行标注的类时,默认会定义一个beanName为我们的类名的bean,对应首字母小写。所以在上述示例中默认就会生成一个类型为Hello,beanName为“hello”的bean。当然我们也可以通过@Component的value属性来指定需要生成的bean的beanName。如下示例中就通过value属性指定了对应生成的bean的beanName为“abc”。
@Component("abc") public class Hello {}
除了@Component外,Spring默认还支持对@Controller、@Service和@Repository注解的扫描。它们可以用来标注在特定bean上,如通常会将@Controller标注在Controller层的类上,将@Service标注在Service层的类上,然后将@Repository标注在Dao层的类上。这些都只是不成文的规定而已,如果用户愿意,我们也可以在Service层上使用@Controller、@Component等进行标注,Spring在扫描到之后都会将它们以对应的bean进行定义。之所以有这么几种不同的注解可以用来定义bean,其中一个主要的原因是我们可以通过不同的注解来区分不同的bean类型,然后可以让Spring在进行扫描的时候只扫描特定类型的注解。当我们使用SpringMVC时,我们常会让SpringMVC对应的ApplicationContext只扫描@Controller,然后让传统的ApplicationContext只扫描除@Controller以外的其它类型的注解,用以将不同类型的bean定义在不同的bean容器中,这样某些针对特定bean容器中的操作就只会针对某些bean产生作用。@Controller、@Service和@Repository也可以通过value属性来指定对应需要生成的bean定义的beanName,默认都是当前Class类名的首字母小写后的结果。
16.2 定义自己的@Component
我们也可以通过@Component定义自己的注解,即在自己的注解上使用@Component进行标注,这样当我们使用自定义的注解标注在Class上时,Spring默认也会将其作为一个bean进行定义。如下我们定义了一个@MyComponent,然后在其上面使用@Component进行了标注,当然这里使用@Controller、@Service和@Repository等进行标注也是可以的,实际上它们的定义也都是使用@Component进行了标注的。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Component public @interface MyComponent {public String value() default "";}
之后我们可以在Class上使用@MyComponent进行标注,Spring在进行扫描时默认也会将它们作为一个bean进行定义。
@MyComponent("abc") public class Hello {}
其实,我们还可以让Spring扫描自定义的注解,让其将标注了自定义注解的Class定义为对应的bean,而我们的自定义注解可以不必使用@Component等原始就支持的注解进行标记。当然,这种用法也是需要进行些许配置的,主要就是告诉Spring需要扫描哪些注解,这部分内容将在后续讲解扫描时的过滤器时进行讲解。
16.3 设置扫描类路径
其实光使用@Component等标注在Class上还不足以使Spring进行扫描并将它们作为一个bean进行定义。我们必须通过配置来告诉Spring进行扫描的类路径。首先我们必须在Spring的配置文件中引入context命名空间,然后通过<context:component-scan/>
标签定义启用Spring扫描@Component等注解的功能。<context:component-scan/>
标签有一个必须指定的属性,base-package,其是用来指定我们需要进行扫描的基本包路径的,指定后Spring将扫描base-package指定的包及其子孙包。如果需要指定多个基础包,则可以通过逗号进行分隔。如下示例,则表示Spring将扫描类路径下com.app.service包及其子孙包,以及com.app.dao包及其子孙包下的所有类以寻找使用@Component等注解进行标注的Class定义为对应的bean。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.app.service,com.app.dao" /> </beans>
定义了<context:component-scan/>
标签后,Spring默认将隐式的启用对注解的支持,即之前介绍的@Autowired等注解的使用,所以使用了该标签以后我们没必要再在Spring配置文件中显式的定义<context:annotation-config/>
了。这可以通过annotation-config属性进行定义,默认是true,改成false就可以禁用自动启用对注解支持。
<context:component-scan base-package="com.app" annotation-config="true"/>
除了必须指定的属性base-package之外,<context:component-scan/>
还可以指定如下属性。
- resource-pattern:表示可以被自动检测的Class的形式,默认为
“**/*.class”
,即所有的class文件。这个只是用来告诉Spring需要对哪些文件进行扫描,而并不是把它们自动定义为对应的bean。这个需要与后续需要介绍的filter区分开。 - use-default-filters:表示使用使用默认的filter,。
<context:component-scan/>
将把哪些Class自动注册到bean容器是由对应的filter来控制的。该属性的值默认为true,即默认会使用默认的filter。而默认的filter会将标注了@Component、@Controller、@Service和@Repository的类,包括这四个注解所标注的注解所标注的类,都会将它们自动注册到bean容器中。 - annotation-config:是否启用对注解的支持,即隐式的启用
<context:annotation-config/>
,默认为true。 - name-generator:默认的beanName生成器,即在没有显式的指定beanName时,自动注册的bean将如何使用默认的beanName。默认将使用Class的简称,即不包含包名的类名称,并将首字母小写作为当前bean的名称。用户可以通过实现
org.springframework.beans.factory.support.BeanNameGenerator
接口并指定其为当前的name-generator来改变对应的策略。 - scope-resolver:指定用于解析bean定义的scope的ScopeMetadataResolver,默认将通过AnnotationScopeMetadataResolver进行解析,而该解析器将根据类上标注的@Scope注解来解析对应的scope。默认没有指定@Scope的都是单例。
- scoped-proxy:表示是否需要为自动检测到的需要加入bean容器中的bean生成对应的代理。默认是不生成。可选值有“no”、“interfaces”和“targetClass”,分别对应不生成、根据接口生成和根据目标class生成。这对需要使用代理的scope是非常有必须要的,如request、session等。更详细的内容请参考先前专门介绍scope的那篇文章。
16.4 使用@Scope指定scope
Spring在通过<context:component-scan/>
自动检测需要添加到bean容器中的bean定义时,默认会将检测到的类单例形式添加到bean容器。如果用户希望使用其它类型的scope,则可以通过在类定义上使用@Scope进行指定。具体的scope是由@Scope的value属性进行指定的,默认是单例。如下是一个通过@Scope指定对应bean的scope为prototype的示例,即是多例形式,每次从bean容器中请求时都会获取一个全新的bean对象。
@Component @Scope("prototype") public class Hello {}
此外,我们还可以通过@Scope的proxyMode属性指定当前bean的代理模式。其对应ScopedProxyMode类型的枚举,可选值有DEFAULT、NO、INTERFACES和TARGET_CLASS,默认是不代理。DEFAULT的作用等同于NO。
@Component @Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS) public class Hello {}
Spring(16)——使用注解进行bean定义相关推荐
- 零配置 之 Spring注解实现Bean定义
转载自 零配置 之 12.3 注解实现Bean定义 --跟我学spring3 12.3 注解实现Bean定义 12.3.1 概述 前边介绍的Bean定义全是基于XML方式定义配置元数据,且在[1 ...
- 我该如何学习spring源码以及解析bean定义的注册
如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...
- Spring之使用注解实例化Bean并注入属性
1.准备工作 (1)导入jar包 除了上篇文章使用到的基本jar包外,还得加入aop的jar包,所有jar包如下 所需jar包 (2)配置xml <?xml version="1.0& ...
- Java Spring Beans.xml里的Bean定义是如何被解析出来的
ClassPathXmlApplicationContext的构造函数里,一部分逻辑是给各个成员变量赋上初始值: 然后是执行refresh操作. 获取ConfigurableListableBeanF ...
- 编码实现Spring 利用@Resource注解实现bean的注入,xml实现基本数据类型的注入
首先分析. 1: 肯定要利用dom4j读取xml配置文件,将所有的bean的配置信息读取出来 2: 利用反射技术,实例化所有的bean 3: 写注解处理器, 利用注解和内省实现依赖对象的注入. 4: ...
- (转)Spring对注解(Annotation)处理源码分析1——扫描和读取Bean定义
1.从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,某些场合可以 ...
- 品Spring:bean定义上梁山
技术不枯燥,先来点闲聊 先说点好事高兴一下.前段时间看新闻说,我国正式的空间站建设已在进行当中.下半年,长征五号B运载火箭将在海南文昌航天发射场择机将空间站核心舱发射升空.预计用2到3年将空间站建好. ...
- Spring Boot-2-核心注解
1. 核心注解 在一个标准的java应用程序的入口处(main),我们需要核心注解.@SpringBootApplication 它是一个组合注解,包含以下注解 @springBootApplicat ...
- 【spring容器启动】之bean的实例化和初始化(文末附:spring循环依赖原理)
本次我们通过源码介绍ApplicationContext容器初始化流程,主要介绍容器内bean的实例化和初始化过程.ApplicationContext是Spring推出的先进Ioc容器,它继承了旧版 ...
- Spring源码分析:Bean加载流程概览及配置文件读取
很多朋友可能想看Spring源码,但是不知道应当如何入手去看,这个可以理解:Java开发者通常从事的都是Java Web的工作,对于程序员来说,一个Web项目用到Spring,只是配置一下配置文件而已 ...
最新文章
- Jvm 系列(十):Java 即时编译器JIT机制以及编译优化
- zookeeper 入门讲解实例 转
- 081212 晴
- docker命令及挂载
- sqlserver2000给账户授予所有的权限_你的位置信息权限设置对了么?
- 负载均衡、分布式、集群的关系
- DataView筛选出最新的十条数据的方法总结;
- 点击startup.bat启动tomcat出现乱码
- LinuxQt打包发布
- iOS 【真机调试-免证书-开发者信任问题】
- 数论系列 求证:设自然数a,b互质,则不能表示成ax+by(x,y为非负整数)的最大整数是ab-a-b
- Tableau 网站流量分析案例之页面指标分析(一)
- 类似 迈图7608 Monentive7608 上海荟研 高新材料 印刷油墨 合成革离型纸 水性涂料基材润湿剂 超润湿剂资料
- 倒立摆的实现 5.步进电机的控制
- android 自动挂断,android实现接通和挂断电话
- Zabbix 监控功能实现(监控数据库,使用percona 优化数据库的监控,监控java应用,Agent端 主动传输数据,Zabbix proxy 的使用,Zabbix 监控 + 智能降噪告警)
- KEAZ128学习(一)----硬件相关
- Linux重启Tomcat
- excel将一个工作表根据条件拆分成多个sheet工作表
- Excel中如何按行排序详细说明
热门文章
- VB.NET 策略模式(下机用户类型选择)
- IOS判断用邮箱登录验证是不是合法的方法
- Invalid attempt to read when no data is present.
- 洛谷 P1057 传球游戏
- Java Web基础回顾 —HTTP
- 关于软件测试里面的Fault Error Failure 差别
- 时间戳TimeStamp处理
- pycharm 修改新建文件时的头部模板(默认为__author__='...')
- Windows 不能在 本地计算机 启动 SQL Server(MSSQLSERVER) 10048
- 19/03/17Python笔记