spring注解驱动开发(一):spring中的@Configuration、@Bean、@ComponentScan注解
在spring中如何使用注解的方式?使用注解方式比XML配置文件方式对比有什么优点?本系列文章是对注解开发基本使用,作为系列文章的第一篇,本篇将来说明@Configuration、@Bean和@ComponentScan注解的使用。
0. 准备工作
- 使用IDEA新建一个Maven工程。
- 在maven工程导入依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
1. 配置文件方式
1.1 配置文件开发步骤:以从容器中获得User对象为例。
- 定义实体类User。
- 定义一个xml配置文件,将User的属性值赋值并注入到容器中。
- 定义测试方法,从容器中获得对象,并打印在控制台
1.2 代码示例。
1. 定义实体类User。
public class User { private String username; private Integer age; public User() { } public User(String username, Integer age) { this.username = username; this.age = age; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + '}'; } }
2. 定义一个xml配置文件,将User的属性值赋值并注入到容器中。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <beans> <bean id="user" class="org.gwsix.ch01.bean.User"> <property name="username" value="张三"/> <property name="age" value="1"/> </bean> </beans> </beans>
3. 定义测试方法,从容器中获得对象,并打印在控制台
@Test
public void testXML() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/org/gwsix/ch01/beans.xml");
User user = (User)applicationContext.getBean("user");
System.out.println(user);
}
执行testXml()方法,控制台打印下面信息,我们成功将bean成功注入到容器中,并可以在容器中获得bean相关信息。
User{username='张三', age=1}
2. 注解方式
2.1 注解开发步骤:以从容器中获得User对象为例。
- 定义实体类User。
- 定义一个配置类,通过配置类将bean注入到容器中。
- 定义测试方法,从容器中获得对象,并打印在控制台
2.2 代码示例。
1. 定义实体类User,和xml配置文件的实体类一致。
2. 定义配置类
@Configuration //标识配置类,相当于beans.xml中的<beans>标签 public class MainConfig { /** * 默认是以方法名作为注册进容器bean的名字,下面三种均可改变容器的bean的名 * methodName * @Bean(value = "user") * @Bean(name = "user") * @return */ @Bean(value = "user") //给容器中注册bean,相当于<bean>,默认方法的名是注入bean名称 public User user(){ return new User("李四",18); } }
3. 定义测试方法,从容器中获得对象,并打印在控制台
@Test public void testConfig() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); User user = (User)applicationContext.getBean("user"); System.out.println(user); //getBeanDefinitionNames() 获得容器中所有输入类的名称 System.out.println("---容器中的组件---"); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames){ System.out.println(name); } }
注意:在注解版本中使用的是AnnotationConfigApplicationContext。
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();获得容器中的bean。
执行textAnnotation(),控制台输出下面内容,说明bean注册到容器中,并可以获取到。
User{username='李四', age=18}
---容器中的组件---
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
user
3. 注解使用小结
1)使用@Configuration向容器注册配置类,这个注解修饰的类类似于xml配置中的<beans>标签。
2)使用@Bean向容器中注册组件,new一个对象返回,类似于<bean>标签,@Bean默认是以方法名作为bean注册到容器,另外使用注解的name或者value属性可 以修改注入到容器的值@Bean(name="user1")\@Bean(name="user1"),查看源码可以看到value其实是name的提个别名。
3)使用注解版本的AnnotationApplicationContation类来初始化容器,参数是使用@Configurtion注解修饰的类。
4)可以使用applicationContext.getBeanDefinitionNames()方法获得容器中所有的bean名称。
4. @ComponentScan注解的使用
@ComponentScan注解功能和<context:component-scan base-package="org.gwsix.ch01"/>作用一样,扫描指定路径下的包。
4.1 简单使用@ComponentScan注解
1.新建UserController、UserService和UserDao分别用@Controller、@Service和@Repository注解,代码如下:
@Controller public class UserController { } @Service public class UserService { } @Repository public class UserDao { }
2.修改配置类
@Configuration //标识配置类,相当于beans.xml中的<beans>标签 @ComponentScan(value = {"org.gwsix.ch01"}) public class MainConfig { /** * 默认是以方法名作为注册进容器bean的名字,下面三种均可改变容器的bean的名 * methodName * @Bean(value = "user") * @Bean(name = "user") * @return */ @Bean(value = "user") //给容器中注册bean,相当于<bean>,默认方法的名是注入bean名称 public User user(){ return new User("李四",18); } }
3.添加测试方法,查看容器中的bena
@Test public void testComponentScan() { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); System.out.println("---容器中的组件---"); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String name : beanDefinitionNames){ System.out.println(name); } }
执行测试方法,控制台输出下面信息表示新增的类进入到容器中。
---容器中的组件--- org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig userController userDao userService user
4.2 详解@ComponentScan注解
@ComponentScan(value = "org.gwsix.ch01",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class, Service.class})},
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class, Service.class})},
useDefaultFilters = false)
@ComponentScan参数详解
userDefaultFilters=false//禁用以前默认的扫描规则,默认值是true,功能对比配置文件中use-default-filters="false"
excludeFilters={}排除扫描的规则,这个会比includeFilters 后执行,功能对比配置文件中
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
includeFilters = {}使用扫描的规则,如果使用这个,需要把useDefaultFilters = false,功能对比配置文件中
<context:include-filter type="annotation" expression="org.springframework.stereotype.S"/></context:component-scan>
FilterType详解,这是一个枚举不同的枚举值代表不同的过滤规则
FilterType.ANNOTATION 按照注解方式
FilterType.ASSIGNABLE_TYPE, 按照给定的类型,本类和子类,@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE ,value = {UserDao.class}),新建UserDaoImpl类继承UserDao。
FilterType.ASPECTJ, 使用aspectj表达式,不常用
FilterType.REGEX,使用正则表达式
FilterType.CUSTOM;自定义规则,包含过滤指定的规则
FilterType.CUSTOM;自定义规则
public class MyTypeFilter implements TypeFilter { //metadataReader 当前扫描类的信息 //metadataReaderFactory 可以获取其他类的信息 @Override //true 匹配成功,false匹配失败 public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) { //获取当前类的注解信息 AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前类的信息 ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获得当前类的资源信息 路径 Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName(); System.out.println("当前类-->"+className); //类名包含er,注入到bean,可以将@Service去掉 if(className.contains("er")) return true; return false; } }
最后配置类@ComponentScan的参数如下
@ComponentScan(value = "org.gwsix.ch01",
//excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})},
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class, Service.class}),
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE ,value = {UserDao.class}),
@ComponentScan.Filter(type=FilterType.CUSTOM,value = {MyTypeFilter.class})
},
useDefaultFilters = false)
控制台输出结果
当前类-->org.gwsix.ch01.bean.User 当前类-->org.gwsix.ch01.config.MyTypeFilter 三月 22, 2019 10:34:47 上午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition 信息: Overriding bean definition for bean 'user' with a different definition: replacing [Generic bean: class [org.gwsix.ch01.bean.User]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [F:\spring\spring-bean-configuration\target\classes\org\gwsix\ch01\bean\User.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=mainConfig; factoryMethodName=user; initMethodName=null; destroyMethodName=(inferred); defined in org.gwsix.ch01.config.MainConfig] ---容器中的组件--- org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig user myTypeFilter userController userDao userDaoImpl userService
5. @ComponentScan使用小结
1)自定义过滤规则,需要类是实现TypeFilter,重写接口得方法。
2)排除规则是最后执行的,excludeFilters比includeFilters后执行

浙公网安备 33010602011771号