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 ...
随机推荐
- 什么?我往Redis写的数据怎么没了?
大概是因为int没有因为change方法而改变原值,所以就说它传过去的是自身的值,因而叫值传递:User对象经过change方法后,对象的数据变了,就认为是因为实参和形参指向的是同一片内存空间,内存空 ...
- requests + bs4 爬取豌豆荚所有应用的信息
1.分析豌豆荚的接口的规律 - 获取所有app的接口url 2.往每一个接口发送请求,获取json数据 解析并提取想要的数据 app_data: 1.图标 app_img_url 2.名字 app_n ...
- 002使用eop来烧写程序
- flask 中的 werkzeug Local,LocalStack 和 LocalProxy 技术应用
什么是 Local wsgi 每次请求,会把过程进行抽离无状态话,过程数据存储在本次请求的全局变量中,使用到了Local. Local 作为每次请求的全局命令空间,属于每次请求的私有 LocalSta ...
- 安装 redis
官方下载地址:http://redis.io/download,但是官方没有64位的Windows下的可执行程序. 目前有个开源的托管在github上, 地址:https://github.com/S ...
- ArcEngine 里面的日期
问题: 将自己做的GIS系统放到其他系统上的时候发现用 IQueryFilter 进行时间查询的时候报错,原来的系统没有这个问题. 原因: 后来调试代码发现查询的时间里面有中文,显示格式 " ...
- kettle连接oracle数据库报错,ORA-12505
报错信息: Error connecting to database: (using class oracle.jdbc.driver.OracleDriver) Listener refused t ...
- Spring Boot 2.X(十九):集成 mybatis-plus 高效开发
前言 之前介绍了 SpringBoot 整合 Mybatis 实现数据库的增删改查操作,分别给出了 xml 和注解两种实现 mapper 接口的方式:虽然注解方式干掉了 xml 文件,但是使用起来并不 ...
- MySql数据主从同步配置
由于需要配置MySQL的主从同步配置,现将配置过程记录下,已被以后不时之需 MySql数据主从同步 1.1. 同步介绍 Mysql的 主从同步 是一个异步的复制过程,从一个 Master复制到另一 ...
- java类中元素初始化顺序
结论:对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器. public class Test4 { @Tes ...