文档章节

【小平工作日志】Spring注解注入配置:<context:component-scan base-package="**.**"/>详解!

张小平-os
 张小平-os
发布于 2016/10/18 13:28
字数 1170
阅读 241
收藏 0

Spring 从2.5(+)版本开始支持注解注入,为spring配置省了很多事情。但同时因为注解是写入在代码里面的,也损失了灵活操作性。

我们首先看一个注解注入的实际例子,然后再详细介绍context:component-scan的使用。

如果你已经在用spring mvc的注解配置,那么你一定已经在使用注解注入了,本文不会涉及到spring mvc,我们用一个简单的例子来说明问题。

本例中我们会定义如下类:

  1. PersonService类,给上层提供Person相关操作
  2. PersonDao类,给PersonService类提供DAO方法
  3. Person类,定义Person相关属性,是一个POJO
  4. App类,入口类,调用注解注入的PersonService类

 PersonService类实现如下:

package cn.xiaoping.zhang;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PersonService {

	@Autowired
	private PersonDao personDao;
	
	public Person getPerson(int id) {
		return personDao.selectPersonById(id);
	}
}

在Service类上使用了@Service注解修饰,在它的私有字段PersonDao上面有@Autowired注解修饰。@Service告诉spring容器,这是一个Service类,默认情况会自动加载它到spring容器里。而@Autowired注解告诉spring,这个字段是需要自动注入的。

PersonDao类:

package cn.xiaoping.zhang;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;

@Scope("singleton")
@Repository
public class PersonDao {

	public Person selectPersonById(int id) {
		Person p = new Person();
		p.setId(id);
		p.setName("Person name");
		return p;
	}
}

在PersonDao类上面有两个注解,分别为@Scope和@Repository,前者指定此spring bean的scope是单例,你也可以根据需要将此bean指定为prototype,@Repository注解指定此类是一个容器类,是DA层类的实现。这个类我们只是简单的定义了一个selectPersonById方法,该方法的实现也是一个假的实现,只是声明了一个Person的新实例,然后设置了属性,返回他,在实际应用中DA层的类肯定是要从数据库或者其他存储中取数据的。

Person类:

package cn.xiaoping.zhang;

public class Person {
	private int id;
	private String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

App类:

package cn.xiaoping.zhang;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;



public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("/spring.xml");
        PersonService service = appContext.getBean(PersonService.class);
        Person p = service.getPerson(1);
        System.out.println(p.getName());
    }
}

在App类的main方法中,我们初始化了ApplicationContext,然后从中得到我们注解注入的PersonService类,然后调用此对象的getPerson方法,并输出返回结果的name属性。

注解注入也必须在spring的配置文件中做配置,我们看下spring.xml文件的内容:

<!--   第一种方式  -->

<?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.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:component-scan base-package="cn.xiaoping.zhang" use-default-filters="false">
		<context:include-filter type="regex" expression="cn\.xiaoping\.zhang\.[^.]+(Dao|Service)"/>
	</context:component-scan>
</beans>


<!--   第二种方式  -->

<?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.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:component-scan base-package="cn.xiaoping.zhang"/>
</beans>

第一种方式:

context:component-scan节点有两个属性base-package属性告诉spring要扫描的包,use-default-filters="false"表示不要使用默认的过滤器,此处的默认过滤器,会扫描包含@Service,@Component,@Repository,@Controller注解修饰的类,而此处我们处于示例的目的,故意将use-default-filters属性设置成了false。

context:component-scan节点允许有两个子节点<context:include-filter>和<context:exclude-filter>。filter标签的type和表达式说明如下:

Filter Type Examples Expression Description
annotation org.example.SomeAnnotation 符合SomeAnnoation的target class
assignable org.example.SomeClass 指定class或interface的全名
aspectj org.example..*Service+ AspectJ語法
regex org\.example\.Default.* Regelar Expression
custom org.example.MyTypeFilter Spring3新增自訂Type,實作org.springframework.core.type.TypeFilter

在我们的示例中,将filter的type设置成了正则表达式,regex,注意在正则里面.表示所有字符,而\.才表示真正的.字符。我们的正则表示以Dao或者Service结束的类。

我们也可以使用annotaion来限定,如下:

<?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.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	<context:component-scan base-package="cn.xiaoping.zhang" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/> 
	 </context:component-scan>
</beans>

这里我们指定的include-filter(包含的类)的type是annotation,expression则是注解类的全名。

另外context:conponent-scan节点还有<context:exclude-filter>可以用来指定要排除的类,其用法和include-filter一致。

第二种方式:

直接扫描cn.xiaoping.zhang包下并且包含@Service,@Component,@Repository,@Controller注解的类。

最后我们要看下输出的结果了,运行App类,输出:

Person name

讲解完成!

© 著作权归作者所有

张小平-os
粉丝 4
博文 47
码字总数 24178
作品 0
北京
后端工程师
私信 提问
Spring 注解注入详解

1.@Autowired注解(不推荐使用,建议使用@Resource) @Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。@Autowired的标注位置不同,它们都会在Spring在初始化这个b...

wpb王鹏博
2015/06/08
0
0
Spring使用ComponentScan扫描Maven多模块工程的其它模块

说明:在新建好了Maven多模块工程后,如果想要在其它模块也能使用Spring的对象管理,比如@Autowrited这些注入方式,那么就必须开启包扫描的功能才能使其进行注入到Spring的对象管理中。 解决...

easonjim
2018/01/20
0
0
为什么applicationContext.xml和spring-servlet.xml中都有注解过滤 和<context:component-scan base-package="myproject.

在刚学习SpringMVC框架整合时,你也许会产生疑问为什么Spring.xml和SpringMVC.xml中都有注解过滤。 和 在这里有一个比较有意思的问题,初学者也会产生困惑,那么他究竟有何不同?我思考和查询...

yaohong
2016/09/25
0
0
spring组件扫描<context:component-scan/>使用详解

关于spring自动检测组件的使用方式网上太多了,而且也不是我记录的重点,我想说下一点可能你还不知道的经验 我们知道如果不想在xml文件中配置bean,我们可以给我们的类加上spring组件注解,只...

长平狐
2012/11/28
43.2K
2
《Spring Recipes》第一章笔记:Scanning Components from ...

问题 当需要注入的bean太多时,手工进行配置太费时费力,Spring容器提供了指定扫描功能。 解决方案 使用Spring的component scanning功能。可以通过@Component,@Repository, @Service , 和@...

LiJIaming
2012/05/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【AI实战】手把手教你深度学习文字识别(文字检测篇:基于MSER, CTPN, SegLink, EAST等方法)

文字检测是文字识别过程中的一个非常重要的环节,文字检测的主要目标是将图片中的文字区域位置检测出来,以便于进行后面的文字识别,只有找到了文本所在区域,才能对其内容进行识别。 文字检...

雪饼
今天
7
0
思维导图XMind 8 Pro 绿化方法(附序列号)

按部就班: Step 1 -全新下载最新版本的 Xmind 8(注必须是英文官方的版本,中文代{过}{滤}理网站的版本修改过,无法使用pj); Step 2 -安装完毕后,点击文末的下载按钮下载pj补丁文件包,将...

一只小青蛙
今天
10
0
数据结构(ER数据库)设计规范

表命名规范 表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为: [leavel]_[type]_[name] [leavel] 表示数据库表的层级和功能,分为: s:业务无关的系统...

随风溜达的向日葵
今天
6
0
阿里Sentinel控制台源码修改-对接Apollo规则持久化

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel 动态规则扩展 https://github.com/alibaba/Sentinel/wiki......

jxlgzwh
昨天
8
0
在Linux系统中创建SSH服务器别名

如果你经常通过 SSH 访问许多不同的远程系统,这个技巧将为你节省一些时间。你可以通过 SSH 为频繁访问的系统创建 SSH 别名,这样你就不必记住所有不同的用户名、主机名、SSH 端口号和 IP 地...

老孟的Linux私房菜
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部