Spring3.X学习笔记3-基于注解和基于Java类的配置
2017-11-07 17:44
645 查看
上一篇文章里我们主要介绍了基于XML Schemal的配置方式。本篇文章里将介绍另外两种提供Bean定义的方式,基于注解和基于Java类的配置。
下面是使用注解定义一个DAO的Bean:
在上面
除了@Component以外,Spring提供了三个功能基本和@Component等效的注解,它们分别用于对DAO、Service及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解:
@Repository:用于对DAO实现类进行标注;
@Service:用于对Service实现类进行标注;
@Controller:用于对Controller实现类进行标注。
在@Component之外提供这三个注解,是为了让注解类本身的用途更加清晰,此外Spring还赋予了它们一些特殊功能。
在上面
如果仅希望扫描特定的类而非基包下的所有类,那么可以使用resource-pattern属性过滤特定的类,如下所示:
默认情况下resource-pattern属性的值为
一个
**当且仅有一个匹配的**Bean时,Spring将其注入到@Autowired标注的变量中。
如果容器中没有一个和标注变量类型匹配的bean,Spring容器启动时将报
如果容器中有一个以上匹配的Bean时,可以通过@Qualifier注解限定Bean的名称。
对集合类进行标注
如果对类中集合类的变量和方法入参进行@Autowired标注,Spring会将容器中类型匹配的所有Bean都自动注入进来。这是一个很好的特性,所以在这里介绍下。
Spring如果发现变量是一个集合类,则它会将容器中匹配集合元素类型的所有Bean都注入进来。这里,Plugin为一个接口,它拥有两个实现类,分别是OnePlugin和TwoPlugin,这两个实现类都通过@Component标注为Bean,则Spring会将这两个Bean都注入到plugins中。
普通的POJO只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供一个Bean的定义信息。
上面的配置和以下XML配置等效:
Spring提供了一个AnnotationConfigApplicationContext类,它能够直接通过标注@Configuration的Java类启动Spring容器。以下两种方式是等效的:
第一种:
第二种:
可以通过代码一个一个注册配置类,也可以通过@Import将多个配置类组装到一个配置类中,这样仅需要注册这个组装好的配置类就可以启动容器了。
我们既可以在XML配置文件中引用@Configuration的配置,也可以通过Configuration配置类中引用XML配置信息。只要不同形式的Bean定义信息能够加载到Spring容器中,Spring就能足够“智能”的完成Bean之间的装配。
使用场景建议:
————本文结束感谢您的阅读————
1、基于注解的配置
不管是XML还是注解,他们都是表达Bean定义的载体,其实质都是为Spring容器提供Bean定义的信息,表现形式上是将XML定义的东西通过类注解进行描述。Spring从2.0开始引入基于注解的配置方式,在3.0时得到进一步的完善。下面是使用注解定义一个DAO的Bean:
package com.hhxs.bbt.dao; import org.springframework.stereotype.Component; // 1.通过Repository定义一个DAO的Bean @Component("userDao") public class UserDao { ... }
在上面
1处,使用@Component注解在UserDao类声明处对类进行标注,它可以被Spring容器识别,Spring容器自动将POJO转换为容器管理的Bean。它和以下的XML配置是等效的:
<Bean id="userDao" class="com.hhxs.bbt.dao.UserDao">
除了@Component以外,Spring提供了三个功能基本和@Component等效的注解,它们分别用于对DAO、Service及Web层的Controller进行注解,所以也称这些注解为Bean的衍型注解:
@Repository:用于对DAO实现类进行标注;
@Service:用于对Service实现类进行标注;
@Controller:用于对Controller实现类进行标注。
在@Component之外提供这三个注解,是为了让注解类本身的用途更加清晰,此外Spring还赋予了它们一些特殊功能。
1.1 使用注解配置信息启动Spring容器
Spring在2.5 后提供了一个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-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd> <description>Spring公共配置 </description> <!-- 1.扫描类包以应用注解定义的Bean --> <context:component-scan base-package="com.hhxs.bbt" /> </beans>
在上面
1处通过
context命名空间的compnent-scan的base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里的所有类,并从类的注解信息中获取Bean的定义信息。
如果仅希望扫描特定的类而非基包下的所有类,那么可以使用resource-pattern属性过滤特定的类,如下所示:
<context:component-scan base-package="com.hhxs.bbt" resource-pattern="dao/*.class"/>
默认情况下resource-pattern属性的值为
**/*.class,即基包里的所有类。这里我们设置为
dao/*.class,则Spring仅会扫描基包里dao子包中的类。通过resource-pattern属性仅可按资源名称对基包中的类进行过滤,如果需要更详细的过滤,则需要用到
<contex:component-scan>的过滤子元素:
<context:component-scan base-package="com.hhxs.bbt"> <context:include-filter type="regex" expression="com.\hhxs.\bbt.*"/> <context:exclude-filter type="aspectj" expression="com.hhxs.bbt..*Controller+"/> </context>
<context:include-filter>表示要包含的目标类
<context:exclude-filter>表示要排除在外的目标类
一个
<context:component-scan>下可以包含若干个
<context:include-filter>和
<context:exclude-filter>元素。这两个过滤元素均支持多种类型的过滤表达式,如下表所示:
类别 | 示例 | 说明 |
---|---|---|
annotation | com.hhxs.bbt.XxxAnnotation | 所有标注了XxxAnnotation的类。该类型采用目标类是否标注了某个注解进行过滤。 |
assignable | com.hhxs.bbt.XxxService | 所有继承或扩展XxxService的类。该类型采用目标类是否继承或扩展某个特定类进行过滤。 |
aspectj | com.hhxs.bbt..*Service+ | 所有类名以Service结束的类及继承或扩展它们的类。该类型采用AspectJ表达式进行过滤。 |
regex | com.hhxs.bbt..* | 所有com.hhxs.bbt类包下的类。该类型采用正则表达式根据目标类的类名进行过滤。 |
custom | com.hhxs.bbt.XxxTypeFilter | 采用XxxTypeFilter通过代码的方式根据过滤规则。该类必须实现org.springframework.core.type.TypeFilter接口 |
1.2 自动装配Bean
spring使用@Autowired注解实现Bean的依赖注入。@Autowired默认按类型匹配的方式,在容器查找匹配Bean,**当且仅有一个匹配的**Bean时,Spring将其注入到@Autowired标注的变量中。
package com.hhxs.bbt.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class LogonService { @Autowired private LogDao logDao; @Autowired private UserDao userDao; ... }
如果容器中没有一个和标注变量类型匹配的bean,Spring容器启动时将报
NoSuchBeanDefinitionException异常。如果希望不抛出异常可以使用@Autowired(required=false)进行标注。默认情况下,@Autowired的required属性值为true。
如果容器中有一个以上匹配的Bean时,可以通过@Qualifier注解限定Bean的名称。
package com.hhxs.bbt.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class LogonService { @Autowired private LogDao logDao; @Autowired @Qualifier("userDao") private UserDao userDao; ... }
对集合类进行标注
如果对类中集合类的变量和方法入参进行@Autowired标注,Spring会将容器中类型匹配的所有Bean都自动注入进来。这是一个很好的特性,所以在这里介绍下。
package com.hhxs.bbt.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class MyComponent { // Spring会将容器中所有类型为Plugin的Bean注入到这个变量中 @Autowired(required=false) private List<Plugin> plugins; public List<Plugin> getPlugins() { return plugins; } }
Spring如果发现变量是一个集合类,则它会将容器中匹配集合元素类型的所有Bean都注入进来。这里,Plugin为一个接口,它拥有两个实现类,分别是OnePlugin和TwoPlugin,这两个实现类都通过@Component标注为Bean,则Spring会将这两个Bean都注入到plugins中。
2、基于Java类的配置
2.1 使用Java类提供Bean定义信息
JavaConfig是Spring的一个子项目,它旨在通过Java类的方式提供Bean的定义信息。Spring3.0基于Java类配置的核心即取材于JavaConfig。普通的POJO只要标注@Configuration注解,就可以为Spring容器提供Bean定义的信息了,每个标注了@Bean的类方法都相当于提供一个Bean的定义信息。
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // 1.将一个POJO标注定义为Bean的配置类 @Configuration public class AppConf { // 2.以下两个方法定义了两个Bean,并提供了Bean的实例化逻辑 @Bean public UserDao userDao() { return new UserDao(); } @Bean public LogDao logDao() { return new LogDao() } @Bean public LogonService logonService() { LogonServcie logonService = new LogonService(); // 将上面2处定义的Bean注入到logonService的Bean logonService.setLogDao(logDao()); logonService.setUserDao(userDao()); return logonService; } }
1处在AppConf类的定义处标注了@Configuration注解,说明这个类可用于为Spring提供Bean信息。类的方法出可以标注@Bean注解,Bean的类型由方法返回值类型决定,名称默认和方法名相同,也可通过@Bean(name=”userDao”)显示指定Bean的名称。
上面的配置和以下XML配置等效:
<bean id="userDao" class="com.hhxs.bbt.dao.UserDao" /> <bean id="logDao" class="com.hhxs.bbt.dao.LogDao" /> <bean id="userDao" class="com.hhxs.bbt.conf.LogonService" p:logDao-ref="userDao" p:userDao-ref="logDao" />
2.2 使用基于Java类的配置信息启动Spring容器
2.2.1 直接通过@Configuration类启动Spring容器Spring提供了一个AnnotationConfigApplicationContext类,它能够直接通过标注@Configuration的Java类启动Spring容器。以下两种方式是等效的:
第一种:
package com.hhxs.bbt.conf; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class JavaConfigTest { public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class); LogonService logonService = ctx.getBean(logonService.class); logonService.printHello(); } }
第二种:
package com.hhxs.bbt.conf; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class JavaConfigTest { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); // 注册多个@Configuration配置类 ctx.register(DaoConfig.Class); ctx.register(ServiceConfig.class); // 刷新容器以应用这些注册的配置类 ctx.refresh(); LogonService logonService = ctx.getBean(logonService.class); logonService.printHello(); } }
可以通过代码一个一个注册配置类,也可以通过@Import将多个配置类组装到一个配置类中,这样仅需要注册这个组装好的配置类就可以启动容器了。
package com.hhxs.bbt.conf; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.context.annotation.Import; @Configurable @Import(DaoConfig.class) public class ServiceConfig { @Bean public LogonService logonService() { LogonService logonService = new LogonService(); return logonService; } }
我们既可以在XML配置文件中引用@Configuration的配置,也可以通过Configuration配置类中引用XML配置信息。只要不同形式的Bean定义信息能够加载到Spring容器中,Spring就能足够“智能”的完成Bean之间的装配。
3、不同配置方式比较
配置方式比较:– | 基于XML配置 | 基于注解配置 | 基于Java类配置 |
---|---|---|---|
Bean定义 | <bean class="com.hhxs.bbt.UserDao"> | Bean实现类出通过标注 @Component、@Repository、@Service、@Controller | 在标注了@Configuration的Java类中,通过在类方法上标注@Bean定义一个Bean。方法必须提供Bean的实例化逻辑。 |
Bean名称 | 通过的id或name属性定义 | 通过注解的value属性定义,如@Component(“userDao”)。默认名称为小写字母打头的类名(不带包名):userDao | 通过@Bean的name属性定义,如@Bean(“userDao”),默认名称为方法名。 |
Bean注入 | 通过子元素或通过p命名空间的动态属性 | 通过在成员变量或方法入参出标注@Autowired,按类型匹配自动注入 | 可以通过在方法处通过@Autowired使方法入参绑定Bean,然后在方法中通过代码进行注入,还可以通过调用配置类的@Bean方法进行注入 |
Bean生命过程方法 | 通过的init-method和destory-method属性指定Bean实现类的方法名。最多只能指定一个初始化方法和一个销毁方法 | 通过在目标方法上标注@PostConstruct和@PreDestroy注解指定初始化或销毁方法,可以定义任意多个方法 | 通过@Bean的initmethod或destoryMethod指定一个初始化或销毁方法。 |
Bean作用范围 | 通过的scope属性指定 | 通过在类定义出标注@Scope指定 | 通过在Bean方法定义处标注@Scope指定 |
Bean延迟初始化 | 通过的lazy-init属性指定,默认为default,继承与的default-lazy-init设置,该值默认为false | 通过在类定义处标注@Lazy指定,如@Lazy(true) | 通过在Bean方法定义处标注@Lazy指定 |
– | 基于XML配置 | 基于注解配置 | 基于Java类配置 |
---|---|---|---|
适合场景 | 1)Bean实现类来源于第三方类库 2)命名空间的配置 | Bean实现类是当前项目开发的, 可以直接在Java类中使用基于注解的配置 | 基于Java类配置的优势在于 可以通过代码方式控制Bean初 始化的整体逻辑。 |
相关文章推荐
- Spring入门学习笔记(2)——基于Java的配置
- Spring学习(13)--- 基于Java类的配置Bean 之 @Configuration & @Bean注解
- 18.笔记JAVASpring框架学习————基于注解配置Bean之二
- 17.笔记JAVA Spring框架学习————基于注解配置Bean之一
- Java 学习笔记06:Spring 基于注解(Annotation)的AOP
- JavaWeb学习笔记-spring-06-ioc-基于注解配置
- JavaWeb学习笔记-spring-07-ioc-基于java类的配置
- Java 学习笔记05:Spring 基于注解(Annotation)的IOC
- spring学习笔记 -- day04 基于注解的配置
- Spring学习(14)--- 基于Java类的配置Bean 之 @ImportResource & @Value 注解
- Spring学习(15)--- 基于Java类的配置Bean 之 @Bean & @Scope 注解
- Spring学习笔记(12.基于java的容器注解)
- [原创]java WEB学习笔记103:Spring学习---Spring Bean配置:基于注解的方式(基于注解配置bean,基于注解来装配bean的属性)
- Spring学习笔记--使用Spring基于Java的配置
- Spring 学习笔记(6)—— 基于注解的配置
- spring学习笔记10--Spring+jdbc组合开发(注解方式配置事务)
- Spring学习笔记(六)基于xml文件方式配置事物
- Java 学习笔记14:Spring 数据库数据源DBCP配置说明
- 基于注解的spring3.0.x MVC学习笔记(二)
- Java 学习笔记04:Spring XML配置文件Bean