• 概述
  • 使用注解定义Bean
  • 扫描注解定义的Bean
    • 使用步骤
    • 扫描特定的类 resource-pattern
      • 实例
    • include-filter exclude-filter过滤子元素的使用
      • 支持多种类型的过滤表达式
      • 实例
    • use-default-filters属性
      • 实例

概述

前几篇博文中主要讲述了基于XML的配置。

不管是XML还是注解,他们都是在表达Bean定义的载体,其实质都是为Spring容器提供Bean定义的信息,在表现形式上都是将XML定义的内容通过类注解进行描述。

基于注解的配置方式,在Spring2.0引入,Spring2.5完善,Spring4.0得到了进一步的增强。

我们知道,Spring容器成功启动的三大要件分别是:

  1. bean的定义信息
  2. bean的实现类
  3. Spring本身

如果采用XML的配置,则Bean的定义信息和Bean的实现类本身是分离的。
而如果采用基于注解的配置方式,则Bean的定义信息通过Bean实现类上标注的注解实现。


使用注解定义Bean

在另外一篇博客中:Spring-Spring MVC + Spring JDBC + Spring Transaction + Maven 构建web登录模块

以案例来说明:

// 通过Spring注解定义一个DAO(这里略微改动了下,使用@Component ,更合适的是@Repository,仅仅是为了演示)
@Component
public class UserDao {.......}

使用@Component注解在UserDao类声明处对类进行标注,它可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。

它和下面的XML配置是等效的

<bean id="userDao" class="com.xgj.dao.UserDao">

使用注解的方式,默认生成的beanId为类名的首字母小写,也可指定其id,如:@Service("xgjService")

除了@Component注解外,Spring还提供了3个功能基本和@Component等效的注解,分别用于对DAO、Service和Web层的Controller进行注解

  • @Repository用于对DAO实现类进行标注
  • @Service用于对Service实现类进行标注
  • @Controller用于对Controller实现类进行注解

之所以要在@Component之外提供3个特殊的注解,是为了让标注类本身的用途清晰化,当然了完全可以用@Component替代这3个特殊的注解, 但是我们推荐使用特定的注解标注特定的Bean,这样可以明确的了解Bean的真是身份


扫描注解定义的Bean

Spring提供了一个context命名空间,它提供了通过扫描类包以应用注解定义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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean --><context:component-scan base-package="com.xgj.ioc.configuration"/></beans>

使用步骤

  1. 首先声明context命名空间和schema文件

  2. 然后通过context命名空间的component-scan的base-package属性指定一个需要扫描的基类包,Spring容器会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。


扫描特定的类 resource-pattern

假设我们希望扫描特定的类,而非基包下所有的类,怎么办呢?

Spring context命名空间提供了resouce-pattern属性过滤出特定的类

    <!-- 通过resource-pattern使Spring加载特定的Bean --><context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern"resource-pattern="scan/*.class"/>

这里设置的基类包为com.xgj.ioc.configuration.resourcePattern,默认情况下resource-pattern属性的值为 **./*.class,即基类包里所有的类。

如果有设置为scan/*.class,则Spring仅会扫描基类包里scan子包中的类。

实例

通过配置文件指定Spring只加载 scan目录下的类的注解,测试resource-pattern属性。

配置文件:

<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 通过resource-pattern使Spring加载特定的Bean --><context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern"resource-pattern="scan/*.class"/></beans>

scan目录下的POJO

package com.xgj.ioc.configuration.resourcePattern.scan;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class Pilot {@Autowiredprivate Plane plane;public void drivePlane() {plane.fly();}
}
package com.xgj.ioc.configuration.resourcePattern.scan;import org.springframework.stereotype.Component;@Component
public class Plane {private String brand;private String color;private int speed;public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}public void introduce() {System.out.println("Plane information【 brand:" + brand + ",color:"+ color + ",speed:" + speed);}public void fly() {System.out.println("Plane begins to  fly");}
}

测试类:

package com.xgj.ioc.configuration.resourcePattern.scan;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ConfigBeanTest {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/ioc/configuration/resourcePattern/resourcePatternBeans.xml");Pilot pilot = ctx.getBean("pilot", Pilot.class);pilot.drivePlane();Plane plane = ctx.getBean("plane", Plane.class);plane.setBrand("A380");plane.setColor("White");plane.setSpeed(800);plane.introduce();}
}

NoScan包下的POJO (PilotNoScan、PlaneNoScan)仅仅类名不同(同名的话,默认ID相同,Spring加载会报错。)

测试类

package com.xgj.ioc.configuration.resourcePattern.noScan;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class ConfigBeanTest {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:com/xgj/ioc/configuration/resourcePattern/resourcePatternBeans.xml");PilotNoScan pilot = ctx.getBean("pilotNoScan", PilotNoScan.class);pilot.drivePlane();PlaneNoScan plane = ctx.getBean("planeNoScan", PlaneNoScan.class);plane.setBrand("A380-NoScan");plane.setColor("White-NoScan");plane.setSpeed(800);plane.introduce();}
}

运行scan报下的测试类

运行noScan报下的测试类,报错

No bean named 'pilotNoScan' available

说明,Spring容器并没有实例化这个类。resource-pattern起了作用。

当我们去掉配置文件中的 resource-pattern="scan/*.class"后,再此运行

可见,Spring容器可以正确加载并实例化Bean


include-filter exclude-filter过滤子元素的使用

通过resource-pattern属性可以按照资源名称对基类包中的类进行过滤,如果我们有个需求:仅需过滤基类包中实现了XxxService接口的类或者标注了某个特定注解的类等 ,该怎么办呢?

Spring的<context:componet-scan>为我们提供了过滤子元素,我们可以轻松的通过其实现上面的需求。

<context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern"resource-pattern="scan/*.class"><context:include-filter type="regex" expression="com\.xgj\.ioc\.configuration\.resourcePattern\.scan.*"/>   <context:exclude-filter type="aspectj" expression="com.xgj.ioc.configuration.resourcePattern..*Controller+"/>
</context:component-scan>
  • <context:include-filter>表示要包含的目标类
  • <context:exclude-filter>表示要排除的目标类
  • 一个<context:component-scan>下可以有多个<context:include-filter><context:exclude-filter>元素

支持多种类型的过滤表达式

类别 示例 说明
annotation com.xgj.XxxAnnotation 所有标注了XxxAnnotation的类。该类型采用目标类是否标志了某个注解进行过滤
assignable com.xgj.XxService 所有继承或扩展XXXService的类。该类型采用目标类是否继承或者扩展了某个特定类进行过滤
aspectj com.xgj..*Service+ 所有类名以Service结束的类及继承或者扩展他们的类。该类型采用AspectJ表达式进行过滤
regex com.xgj.auto..* 所有com.xgj.auto类包下的类。该类型采用正则表达式根据目标类的类名进行过滤
custom com.xgj.XxxTypeFilter 采用XxxTypeFilter代码方式实现过滤规则,该类必须实现org.springframework.core.type.TypeFilter接口

在所有的过滤类型中,除了custom类型外,aspectj的过滤表达能力是最强的,可以轻易实现其他类型所能表达的过滤规则。

实例

我们先将测试类改下名,保证不重名,否则会抛出如下异常

Annotation-specified bean name 'configBeanTest' for bean class [com.xgj.ioc.configuration.resourcePattern.scan.ConfigBeanTest] conflicts with existing, non-compatible bean definition of same name and class [com.xgj.ioc.configuration.resourcePattern.noScan.ConfigBeanTest]

配置文件:

<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 通过resource-pattern使Spring加载特定的Bean <context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern" resource-pattern="scan/*.class"/> --><!-- context:include-filter context:exclude-filter --><context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern"><context:include-filter type="regex"expression="com\.xgj\.ioc\.configuration\.resourcePattern.*" /><context:exclude-filter type="aspectj" expression="com.xgj.ioc.configuration.resourcePattern..*NoScan+"/></context:component-scan></beans>

配置文件解析:

<context:include-filter type="regex"expression="com\.xgj\.ioc\.configuration\.resourcePattern.*" />

使用<context:include-filter> ,通过regex正则表达式过滤方式,包含com.xgj.configuration.resourcePattern目录下的所有类,按照项目结果包括scan和noScan子包中的注解类。

<context:exclude-filter type="aspectj"    expression="com.xgj.ioc.configuration.resourcePattern..*NoScan+"/>

使用<context:exclude-filter>,通过aspectj的过滤方式,排除掉com.xgj.ioc.configuration.resourcePattern包及子包下所有以NoScan+结尾的类,按照项目结构即排除掉noScan子包下的注解类。


其余POJO和测试类同上。

测试scan包下的测试类

测试noScan包下的测试类

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pilotNoScan' available

可见 <context:include-filter><context:exclude-filter>标签起了作用。


use-default-filters属性

use-default-filters属性默认值为true,表示会对标注@Component、@Controller、@Service、@Reposity的Bean进行扫描。

<context:component-scan>首先根据 exclude-filter列出需要排除的黑名单,然后再根据include-filter流出需要包含的白名单。 但是由于use-default-filters属性默认值的作用,看下下面的配置片段,不但会对@Controller的bean进行扫描,还会会对@Component、@Service、@Reposity的Bean进行扫描。

    <context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern"><context:include-filter type="annotation"expression="org.springframework.stereotype.Controller" /></context:component-scan>

换句话讲,上面的配置和不加<context:include-filter>的效果是一样的,如果仅仅想扫描@Controller的bean,必须将use-default-filters属性设置为false.

如下所示

<context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern" use-default-filters="false"><context:include-filter type="annotation"expression="org.springframework.stereotype.Controller" />
</context:component-scan>

实例

配置文件

<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.xgj.ioc.configuration.resourcePattern" use-default-filters="false"><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/></context:component-scan></beans>

运行测试类 com.xgj.ioc.configuration.resourcePattern.scan.ConfigBeanTest

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pilot' available

如果我们去掉use-default-filters=”false”试下呢?

由此可见 use-default-filters=”false” 起到了只加载或者排除特定注解的功能。

Spring-基于注解的配置[01定义Bean+扫描Bean]相关推荐

  1. (spring-第4回【IoC基础篇】)spring基于注解的配置

    (spring-第4回[IoC基础篇])spring基于注解的配置 基于XML的bean属性配置:bean的定义信息与bean的实现类是分离的. 基于注解的配置:bean的定义信息是通过在bean实现 ...

  2. Spring 基于注解的配置

    转载自  Spring 基于注解的配置 基于注解的配置 从 Spring 2.5 开始就可以使用注解来配置依赖注入.而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注 ...

  3. spring基于注解的配置

    转自:https://www.cnblogs.com/mesopotamia/p/4963659.html 基于XML的bean属性配置:bean的定义信息与bean的实现类是分离的. 基于注解的配置 ...

  4. Spring基于注解的配置概述

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/annotation-based-configuration.html: 从Spring 2.5开始 ...

  5. Spring学习(六)-Bean作用域与基于注解的配置

    Bean作用域 在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域.作用域将对Bean的生命周期和创建方式产生影响.Spring一般采用sc ...

  6. Spring IoC — 基于注解的配置

    基于XML的配置,Bean定义信息和Bean实现类本身是分离的,而采用基于注解的配置方式时,Bean定义信息即通过在Bean实现类上标注注解实现. @Component:对类进行标注,Spring容器 ...

  7. spring 基于注解的控制器配置

    http://ttaale.iteye.com/blog/787586 spring 基于注解的控制器配置 博客分类: spring SpringBeanServletMVCWeb 13.12. 基于 ...

  8. 从源码分析 Spring 基于注解的事务

    从源码分析 Spring 基于注解的事务 在spring引入基于注解的事务(@Transactional)之前,我们一般都是如下这样进行拦截事务的配置: <!-- 拦截器方式配置事务 --> ...

  9. Spring基于注解的方式二

    Spring基于注解二 上一次介绍了很多的关于spring的基本的注解,这篇文章描述一下关于Spring注解的基本的原理,从简单的例子入手 @Configuration @Import({Color. ...

最新文章

  1. 除了密钥,公有云还有哪些安全保护方式
  2. html文件里的scr是什么,HTML中关于url、scr、href的区别
  3. 数据中心设计的六个关键考虑因素
  4. linux系统适合电脑小白吗,linux小白说说用linux的感受
  5. 实现串匹配的并行算法_5-1-KMP模式匹配
  6. CodeForces - 1525D Armchairs(dp)
  7. Faker库:一个数据造假的神库
  8. (转)unity web 缓存解决方案
  9. Eclipse-复制项目
  10. make files touse cmd line to protect exe
  11. 232.栈实现队列(力扣leetcode) 博主可答疑该问题
  12. 麻瓜编程python_麻瓜编程 - 主页
  13. 【数学建模】CUMCM-2014B 创意平板折叠桌 解题思路整理
  14. OkHttp Events事件
  15. qmainwindow 标题栏_Qt:自定义标题栏(QMainWindow)
  16. Ubuntu解决RTNETLINK answers: File exists
  17. Selenium Gird下文件上传问题的解决(WebUI自动化测试)
  18. python打印电子标签--ghostscript 和reportlab实现
  19. 「纵行科技」完成数亿元B+轮融资,加速落地 LPWAN 2.0「T型战略」
  20. Week6 限时大模拟 A 掌握魔法の东东II

热门文章

  1. zip()和zip(*)的区别与使用
  2. C++基类和派生类的构造函数(二)
  3. centos 安装mysql5.7_Zabbix 4.2.5 安装部署实践详解
  4. Leetcode 215.数组中第k个最大元素 (每日一题 20210713)
  5. 李宏毅线性代数11: 正交(Orthogonality)
  6. ClickHouse 在字节跳动广告场景的应用
  7. Elasticsearch 使用过程中有哪些坑?教你避开这些坑
  8. 数据挖掘学习笔记之人工神经网络(二)
  9. Python入门100题 | 第006题
  10. 优化器 - tf.keras.optimizers.SGD()【TensorFlow2入门手册】