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 ...
随机推荐
- 第二阶段:2.商业需求分析及BRD:7.商业需求文档3
BRD模版 阐述需求来源以及调研分析情况 百度指数工具.定量的数据.发展趋势,是否与公司的战略冲突.环境政策:比如做内容的运营. 决策层看重的! 第二大块. 通过什么方式解决这个需求. 规划能力.类似 ...
- java xml的读取与写入(dom)
首先,先获取到文档对象 private static Document getDocument(String path) { //1.创建DocumentBuilderFactory对象 Docume ...
- python基础[18]——使用django创建一个简易的博客网站
一.页面实现 index.html base.html post.html header.html footer.html <!-- index.html--> {% extends 'b ...
- jquery中报错Uncaught ReferenceError: $ is not defined的解决办法
jquery中报错提示为:Uncaught ReferenceError: $ is not defined 这个错误的原因就是你没有引入jquery库文件或者引入的路径不对造成的
- 使用vue-quill-editor富文本 实现图片上传
1. 下载并引入 import { quillEditor, Quill } from "vue-quill-editor"; import { container, ImageE ...
- vc++ 监控指定路径下文件变化
参考MSDN文档 https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-readdirectorychange ...
- 【C++】几个简单课本例题
// // main.cpp // 2_1 // // Created by T.P on 2018/2/28. // Copyright © 2018年 T.P. All rights reserv ...
- 机器学习之路--Numpy
常用代码 ndarray.dtype 数据类型必须是一样的 常用代码 import numpy #numpy读取文件 world_alcohol = numpy.genfromtxt("wo ...
- DNS服务器红帽5.4搭建图文教程!!!
DNS服务器 挂载光盘 mount 查看光盘所在位置 mount -t iso9660 设备目录 /mnt 表示挂载 软件包安装 所有软件包都在Server目录下 rpm -ivh /mnt/Serv ...
- Theia APIs——事件
上一篇:Theia APIs——Preferences 事件 Theia中的事件或许会让你感到困惑,希望本节能阐述清楚. 来看下面的代码: (来自logger-watcher.ts) @injecta ...