统的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注解开发系列Ⅰ--- 组件注册(上)的更多相关文章

  1. Spring注解开发系列Ⅱ --- 组件注册(下)

    1.@Import注册组件 @Import主要功能是通过导入的方式实现把实例加入springIOC容器中, /** * 给容器注册组件 * 1.包扫描+组件标注注解(@Controller,@Serv ...

  2. 【Spring注解开发】组件注册-使用@Configuration和@Bean给容器中注册组件

    写在前面 在之前的Spring版本中,我们只能通过写XML配置文件来定义我们的Bean,XML配置不仅繁琐,而且很容易出错,稍有不慎就会导致编写的应用程序各种报错,排查半天,发现是XML文件配置不对! ...

  3. 浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配

    Spring注解开发 浅尝Spring注解开发,基于Spring 4.3.12 包含自定义扫描组件.自定义导入组件.手动注册组件.自动注入方法和参数.使用Spring容器底层组件等 配置 @Confi ...

  4. Spring注解开发系列专栏

    这个系列主要是讲Spring注解的使用,可以为后面SpringBoot的学习带来一定的帮助.我觉得从Spring直接过度到SpringBoot还是有点快,还是得需要一个演变的过程.从Spring开发, ...

  5. Spring注解开发系列Ⅵ --- AOP&事务

    注解开发 --- AOP AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,横向重复,纵向抽取.详细的AO ...

  6. Spring注解开发系列Ⅴ --- 自动装配&Profile

    自动装配: spring利用依赖注入和DI完成对IOC容器中各个组件的依赖关系赋值.自动装配的优点有: 自动装配可以大大地减少属性和构造器参数的指派. 自动装配也可以在解析对象时更新配置. 自动装配的 ...

  7. Spring注解开发系列VIII --- SpringMVC

    SpringMVC是三层架构中的控制层部分,有过JavaWEB开发经验的同学一定很熟悉它的使用了.这边有我之前整理的SpringMVC相关的链接: 1.SpringMVC入门 2.SpringMVC进 ...

  8. Spring注解开发系列VII --- Servlet3.0

    Servlet3.0简介 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用 ...

  9. Spring注解开发系列Ⅲ --- 生命周期

    Bean的生命周期 Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解. 首先看下生命周期图: 再谈生命周期之前有一点需要先明确: S ...

随机推荐

  1. 第二阶段:2.商业需求文档MRD:4.MRD-核心目标-产品构成

    竞争对手分析很重要.之后单独讲解.产品经理时刻要关注竞争产品的状态. 1.不同于PRD.这里只是概况.2.产品前景的核心目标就是:KPI(用户使用量:安装量,卸载量,日活数)跟ROI(开发人力,时间, ...

  2. 博帝飚速盘 16G

    设备制造商:  Patriot Memory当前协议  :  USB2.0输入电流  :  300mA 芯片制造商:  群联(Phison)芯片型号  :  PS2251-38闪存颗粒  :  美光( ...

  3. [UWP]XAML中的响应式布局技术

    响应式布局的概念是一个页面适配多个终端及不同分辨率.在针对特定屏幕宽度优化应用 UI 时,我们将此称为创建响应式设计.WPF设计之初响应式设计的概念并不流行,那时候大部分网页设计师都按着宽度960像素 ...

  4. 「洛谷P2397」 yyy loves Maths VI (mode) 解题报告

    P2397 yyy loves Maths VI (mode) 题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居 ...

  5. 「Vijos 1282」「OIBH杯NOIP2006第二次模拟赛」佳佳的魔法照片

    佳佳的魔法照片 背景 佳佳的魔法照片(Magic Photo):如果你看过<哈利·波特>,你就会知道魔法世界里的照片是很神奇的.也许是因为小魔法师佳佳长的太帅,很多人都找他要那种神奇的魔法 ...

  6. python django 基本环境配置

    创建虚拟环境: python -m venv django启动虚拟环境: .\venv\Scripts\activate下载django: pip install django查看django命令: ...

  7. docker-bind挂载

    使用绑定挂载 自Docker早期以来,绑定挂载一直存在.与卷相比,绑定装载具有有限的功能.使用绑定装入时,主机上的文件或目录将装入容器中.文件或目录由其在主机上的完整路径或相对路径引用.相反,当您使用 ...

  8. keuectl命令

    Kubernetes命令行 kubectl用于运行Kubernetes集群命令的管理工具 kubectl命令行语法 kubectl [command] [TYPE] [NAME] [flags] co ...

  9. js原生深拷贝

    /*****************************************************************************************/ 原生js实现深拷 ...

  10. oracle-按年、月、周、日、时、分 分组查询统计数据,无数据补零(connect by)

    目的:统计一段时间内每年.每月.每周.每日.每时.每分数据,无数据时自动补零 思路:1. 生成给定时间段对应日期 2. 将原表中该时间段内的不为0的数据量统计出来 3. 用left join连接起来, ...