Spring注解开发系列Ⅰ--- 组件注册(上)
传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事物,这么做有两个缺点:
1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。
2、在开发中在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。
为了解决这两个问题,Spring引入了注解,通过"@XXX"的方式,让注解与Java Bean紧密结合,既大大减少了配置文件的体积,又增加了Java Bean的可读性与内聚性。
1.@Configuration&@Bean给容器中注册组件
@Configuration可理解为用spring的时候xml里面的<beans>标签
@Bean可理解为用spring的时候xml里面的<bean>标签
xml版:
<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.xsd">
<!--原始方式-->
<bean id="person" class="com.wang.bean.Person">
<property name="name" value="张三"></property>
<property name="age" value="18"></property>
</bean>
</beans>
注解版:
//在配置类里配置
@Configuration//告诉spring这是一个配置类
public class PersonConfig {
@Bean(value = "person") //给spring容器注册一个bean,类型为返回值类型,id是默认是方法名为id,也可以使用value指定
public Person person(){
return new Person("lisi",20);
}
}
2.@ComponentScan-自动扫描组件&指定扫描规则
该注解会自动扫描包路径下面的所有@Controller、@Service、@Repository、@Component 的类
xml版:
<!--包扫描,只要注解了@Component,@Controller等会被扫描-->
<context:component-scan base-package="com.wang" use-default-filters="false" >
<!--排除某个注解,除了Controller其他类都会被扫描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--只包含某个注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
注解版:
@ComponentScan(value = "com.wang"/*excludeFilters = { //排除
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class}) //排除Controller和Service
},*/,includeFilters = { //只包含
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Repository.class})
/*,@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})*/ //自定义注解
},useDefaultFilters = false) //这里要加useDefaultFilters=false让默认的过滤器失效
其中Filter的type的类型有:
1. FilterType.ANNOTATION 按照注解
2. FilterType.ASSIGNABLE_TYPE 按照类型 FilterType.REGEX 按照正则
3. FilterType.ASPECTJ 按照ASPECJ表达式规则
4. FilterType.CUSTOM 使用自定义规则
其中自定义规则类型过滤器需要实现TypeFilter接口:
package com.wang.config; import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter; import java.io.IOException;
//自定义类型过滤器
public class MyTypeFilter implements TypeFilter {
//metadataReader读取到当前扫描到的类的信息
//metadataReaderFactory可以获取其他任何类的信息
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); //获取当前扫描类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();//获取当前扫描类的类信息
Resource resource = metadataReader.getResource();//获取当前扫描类的资源信息 String className = classMetadata.getClassName();
System.out.println("className--->"+className); if (className.contains("Dao")){
return true;
}else {
return false;
} }
}
3.@Scop 设置组件作用域
xml版:
<bean id="person" class="com.wang.bean.Person" scope="prototype">
<property name="name" value="张三"></property>
<property name="age" value="18"></property>
</bean>
注解版:
@Bean
/**
* prototype 多例,ioc容器创建完成后,要获取的时候才会被调用,多次获取会多次调用
* singleton 单例(默认),ioc容器启动会调用方法创建对象放到ioc中,以后直接从容器中获取
* request 同一次请求创建一个实例
* session 同一个session创建一个实例
*
*/
@Scope("prototype")
public Person person(){
System.out.println("添加Person....");
return new Person("张三",23);
}
4.@Lazy 懒加载bean
xml版本:
<bean id="person" class="com.wang.bean.Person" scope="prototype" lazy-init="true">
<property name="name" value="张三"></property>
<property name="age" value="18"></property>
</bean>
注解版:
/**
*
* 单实例bean,默认在容器启动的时候创建对象
* 懒加载:容器启动不创建对象,第一次使用(获取)创建Bean,并初始化,第二次使用就使用第一次创建的对象
*
*/
@Lazy
5.@Conditional按照条件注册bean
@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。下面给个例子,判断当前项目的运行环境,如果是Windows系统,注册id为win的bean,若是Linux系统,注册id为lin的bean 1).实现Condition接口
public class WindowsCondition implements Condition {
/**
*
* @param conditionContext 判断条件能使用的上下文环境
* @param annotatedTypeMetadata 当前标注了condition的注释信息
* @return
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//1.获取ioc的BeanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//2.获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//3.获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//4.获取所有bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
String property = environment.getProperty("os.name");
if (property.contains("Windows")){
return true;
}
else {
return false;
}
}
}
package com.wang.condition; import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata; public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//3.获取当前环境信息
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name"); if (property.contains("Linux")){
return true;
}
else {
return false;
}
}
}
2).在Bean上配置注解
@Configuration
public class ConditionConfig {
/**
* @Conditional({})按照一定条件进行判断,满足条件容器中注册bean,
* 若放在类中,整个配置类中的bean满足条件才会被加载到容器中
*
* 若是windows系统,注册win,若是linux注册lin
*/
@Bean("win")
@Conditional(WindowsCondition.class)
public Person person(){
return new Person("win",22);
} @Bean("lin")
@Conditional(LinuxCondition.class)
public Person person2(){
return new Person("lin",11);
}
@Bean("person")
public Person person3(){
return new Person("person",25);
}
}
Spring注解开发系列Ⅰ--- 组件注册(上)的更多相关文章
- Spring注解开发系列Ⅱ --- 组件注册(下)
1.@Import注册组件 @Import主要功能是通过导入的方式实现把实例加入springIOC容器中, /** * 给容器注册组件 * 1.包扫描+组件标注注解(@Controller,@Serv ...
- 【Spring注解开发】组件注册-使用@Configuration和@Bean给容器中注册组件
写在前面 在之前的Spring版本中,我们只能通过写XML配置文件来定义我们的Bean,XML配置不仅繁琐,而且很容易出错,稍有不慎就会导致编写的应用程序各种报错,排查半天,发现是XML文件配置不对! ...
- 浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
Spring注解开发 浅尝Spring注解开发,基于Spring 4.3.12 包含自定义扫描组件.自定义导入组件.手动注册组件.自动注入方法和参数.使用Spring容器底层组件等 配置 @Confi ...
- Spring注解开发系列专栏
这个系列主要是讲Spring注解的使用,可以为后面SpringBoot的学习带来一定的帮助.我觉得从Spring直接过度到SpringBoot还是有点快,还是得需要一个演变的过程.从Spring开发, ...
- Spring注解开发系列Ⅵ --- AOP&事务
注解开发 --- AOP AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,横向重复,纵向抽取.详细的AO ...
- Spring注解开发系列Ⅴ --- 自动装配&Profile
自动装配: spring利用依赖注入和DI完成对IOC容器中各个组件的依赖关系赋值.自动装配的优点有: 自动装配可以大大地减少属性和构造器参数的指派. 自动装配也可以在解析对象时更新配置. 自动装配的 ...
- Spring注解开发系列VIII --- SpringMVC
SpringMVC是三层架构中的控制层部分,有过JavaWEB开发经验的同学一定很熟悉它的使用了.这边有我之前整理的SpringMVC相关的链接: 1.SpringMVC入门 2.SpringMVC进 ...
- Spring注解开发系列VII --- Servlet3.0
Servlet3.0简介 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用 ...
- Spring注解开发系列Ⅲ --- 生命周期
Bean的生命周期 Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解. 首先看下生命周期图: 再谈生命周期之前有一点需要先明确: S ...
随机推荐
- 美国权威媒体CRN预测:2020年值得关注的10个新兴云计算趋势
云计算在过去一年里极速发展,其速度之快,让人难以预测未来会发生什么.即使依照这些趋势而新发明的技术在不断变化并且极其脆弱,而推动这些趋势和技术不断发展的企业和组织最终也很有可能发生变化,但不妨碍这些大 ...
- 004使用u-boot烧写裸版程序
- 从零开始のcocos2dx生活(十)ScrollView
目录 简介 基础变量 ScrollViewDelegate Direction _dragging _container _touchMoved _bounceable _touchLength 方法 ...
- Java工作流引擎节点接收人设置20种规则讲解一
关键字: 驰骋工作流程快速开发平台 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 开发者表单 拖拽式表单 工作流系统CCBPM节点访问规则接收人规则 适配数据库: o ...
- Ant Design中getFieldDecorator方法的特殊用法(小bug)
记录Ant Design中getFieldDecorator方法的特殊的一个用法 了解Ant Design表单的小伙伴都知道,getFieldDecorator在大部分情况下是用来绑定一个控件的,即像 ...
- Map and HashMap
1.1.1. Map 接口 java提供了一组可以以键值对(key-value)的形式存储数据的数据结构,这种数据结构称为Map.我们可以把Map看成一个多行两列的表格,其中第一列存放key,第二列存 ...
- C#.Net ComboBox控件设置DropDownList之后背景颜色问题,以及发现的微软的一个BUG
先说背景颜色问题怎么处理. C#.Net WinForm中如果设置ComboBox的DropDownStyle为DropDownList,控件背景色会变成灰色,并且这个时候ComboBox控件的Bac ...
- Java set接口之HashSet集合原理讲解
Set接口 java.util.set接口继承自Collection接口,它与Collection接口中的方法基本一致, 并没有对 Collection接口进行功能上的扩充,只是比collection ...
- Java StringBuilder类
StringBuilder的原理 String类 字符串是常量,它们的值在创建之后不能更改 字符串的底层是一个被final修饰的数组,不能改变 private final byte[] value; ...
- 消息队列rabbitmq的五种工作模式(go语言版本)
前言:如果你对rabbitmq基本概念都不懂,可以移步此篇博文查阅消息队列RabbitMQ 一.单发单收 二.工作队列Work Queue 三.发布/订阅 Publish/Subscribe 四.路由 ...