spring从2.5版本开始支持注解注入,注解注入能够省去不少的xml配置工做。因为注解是写入java代码中的,因此注解注入会失去必定的灵活性,咱们要根据须要来选择是否启用注解注入。java
咱们首先看一个注解注入的实际例子,而后再详细介绍context:component-scan的使用。正则表达式
若是你已经在用spring mvc的注解配置,那么你必定已经在使用注解注入了,本文不会涉及到spring mvc,咱们用一个简单的例子来讲明问题。spring
本例中咱们会定义以下类:数据库
- PersonService类,给上层提供Person相关操做
- PersonDao类,给PersonService类提供DAO方法
- Person类,定义Person相关属性,是一个POJO
- App类,入口类,调用注解注入的PersonService类
PersonService类实现以下:express
package cn.outofmemory.spring; 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,这个字段是须要自动注入的。swift
PersonDao类:mvc
package cn.outofmemory.spring; 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层的类确定是要从数据库或者其余存储中取数据的。app
Person类:ui
package cn.outofmemory.spring; 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; } }
Person类是一个POJO。this
App类:
package cn.outofmemory.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Hello spring! from outofmemory.cn * */ 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.outofmemory.spring" use-default-filters="false"> <context:include-filter type="regex" expression="cn\.outofmemory\.spring\.[^.]+(Dao|Service)"/> </context:component-scan> </beans>
这个配置文件中必须声明xmlns:context 这个xml命名空间,在schemaLocation中须要指定schema:
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
这个文件中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.outofmemory.spring" 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一致。
最后咱们要看下输出的结果了,运行App类,输出:
2014-5-18 21:14:18 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1cac6db: startup date [Sun May 18 21:14:18 CST 2014]; root of context hierarchy 2014-5-18 21:14:18 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring.xml] 2014-5-18 21:14:18 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1fcf790: defining beans [personDao,personService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy Person name
前几行都是spring输出的一些调试信息,最后一行是咱们本身程序的输出。
本文源码下载:spring-DI-annotation.zip