Spring注解开发-全面解析常用注解使用方法之组件注册
本文github位置:https://github.com/WillVi/Spring-Annotation/
1. @Configuration
@Configuration
//配置注解类似 applicationcontext.xml 只是将xml配置改为 注解方式进行
2. @ComponentScan
进行包扫描会根据注解进行注册组件,value="包名"
@ComponentScan(value="cn.willvi")
FilterType
- ANNOTATION 通过注解类型 列如 @Controller为Controller.class @Service 为 Service.class
- ASSIGNABLE_TYPE, 一组具体类 例如PersonController.class
- ASPECTJ, 一组表达式,使用Aspectj表达式命中类
- REGEX 一组表达式,使用正则命中类
- CUSTOM 自定义的TypeFilter.
excludeFilters
excludeFIlters = Filter[] 根据规则排除组件
@ComponentScan(value="cn.willvi",excludeFilters= {
//根据注解排除注解类型为@Controller
@Filter(type=FilterType.ANNOTATION,value= {Controller.class}),
@Filter(type=FilterType.ASSIGNABLE_TYPE,value= {IncludeConfig.class,MainConfig.class}),
})
includeFilters
includeFIlters = Filter[] 根据规则只包含哪些组件(ps:useDefaultFilters设置为false)
@ComponentScan(value="cn.willvi",includeFilters= {
//根据注解类型扫描注解类型为@Controller的类
@Filter(type=FilterType.ANNOTATION,value= {Controller.class})
},useDefaultFilters=false)
使用自定义TypeFilter
当过滤有特殊要求时,可以实现TypeFilter来进行自定的过滤规则
自定义TypeFilter:
public class CustomTypeFilter implements TypeFilter {
/**
* metadataReader the metadata reader for the target class 读取当前扫描类的信息
* metadataReaderFactory a factory for obtaining metadata readers
* for other classes (such as superclasses and interfaces) 获取其他类的信息
*/
public boolean match(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
//获取当前扫描类信息
ClassMetadata classMetadata = reader.getClassMetadata();
//获取当前注解信息
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
//获取当前类资源(类路径)
Resource resource = reader.getResource();
String className = classMetadata.getClassName();
System.out.println("----->"+className);
if(className.contains("PersonService")) {
return true;
}
return false;
}
}
使用:
//自定义过滤组件
@ComponentScan(value="cn.willvi",includeFilters= {
@Filter(type=FilterType.CUSTOM,value= {CustomTypeFilter.class})
},useDefaultFilters=false)
//或者
//自定义过滤组件
@ComponentScan(value="cn.willvi",excludeFilters= {
@Filter(type=FilterType.CUSTOM,value= {CustomTypeFilter.class})})
3. @Bean
注册bean与spring 的xml配置异曲同工之妙只是将xml配置转换为注解
<bean id="person" class="cn.willvi.bean.Person" scope="prototype" >
<property name="age" value="23"></property>
<property name="name" value="willvi"></property>
</bean>
@Scope
在 Spring IoC 容器是指其创建的 Bean 对象相对于其他 Bean 对象的请求可见范围。
singleton单例模式 全局有且仅有一个实例
prototype原型模式 每次获取Bean的时候会有一个新的实例
request 每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
session session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
global session global session作用域类似于标准的HTTP Session作用域,不过它仅仅在基于portlet的web应用中才有意义。
以上5个一般只用第一个和第二个
原型模式使用:
@Bean
@Scope("prototype")
public Person person() {
return new Person("willvi",23);
}
验证:
ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = (Person) ioc.getBean("personScope");
Person person1 = (Person) ioc.getBean("personScope");
//返回true说明为单例
System.out.println(person==person1);
@Lazy
懒加载。当Scope为单例模式时,当容器被初始化时就会被实例化。
当有@Lazy时,在容器初始化时不会被实例化,在获取实例时才会被初始化
单例模式懒加载使用
@Bean
@Scope
@Lazy //去掉和加上看输出结果
public Person person() {
System.out.println("bean初始化");
return new Person("willvi",23);
}
验证:
ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class);
System.out.println("容器初始化完成");
Person person = (Person) ioc.getBean("personScope");
4. Conditional
根据自定义条件注册组件。需要实现Condition
接口
接口实现例子:
package cn.willvi.conditional;
import java.util.LinkedList;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
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 LinuxConditional implements Condition{
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//获取环境
Environment environment = context.getEnvironment();
//获取组件注册类
BeanDefinitionRegistry registry = context.getRegistry();
//判断容器是否包含注册“person02”注册类
boolean containsBeanDefinition = registry.containsBeanDefinition("person02");
//获取当前操作系统并判断是否为Linux是的话 返回true;
//返回true表示满足条件,ioc容器会注册该bean。反之则不会
String property = environment.getProperty("os.name");
if(property.contains("Linux")) {
return true;
}
return false;
}
}
运用:
//根据自定义条件进行注测
//给定自定义的class
@Conditional({WindowConditional.class})
@Bean
public Person person01() {
return new Person("windows",11);
}
@Conditional({LinuxConditional.class})
@Bean
public Person person02() {
return new Person("linux",11);
}
----------------------------------------------------------
//也可以直接写在类前面
//表示类中统一满足该条件才会被注册
@Configuration
@Conditional({WindowConditional.class})
public mainConfig(){
....
}
5. @Import
直接通过
@Import({Dog.class,Pig.class})
实现ImportSelector接口
@Import({Dog.class,ImportSelector.class})
package cn.willvi.selector; import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata; /**
* ImportSelector @Import注解其中之一 选择器例子
* @author willvi
*
*/
public class AnnoImportSelector implements ImportSelector{ /**
* AnnotationMetadata获取当前类的注解信息
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//需要返回全类名
String [] beans = {"cn.willvi.bean.Pig"};
return beans;
} }
实现ImportBeanDefinitionRegistrar实现手工注册组件
@Import({Dog.class,AnnoImportBeanDefinitionRegistrar.class})
package cn.willvi.selector; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata; import cn.willvi.bean.Person; /**
*
* ImportBeanDefinitionRegistrar接口实现
* @author willvi
*
*/
public class AnnoImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ /**
* AnnotationMetadata获取当前类的注解信息
* BeanDefinitionRegistry 注册类 可以手工注册组件
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Person.class);
//参数为:bean id名 bean定义信息
registry.registerBeanDefinition("person", rootBeanDefinition); } }
使用:
package cn.willvi.config; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import cn.willvi.bean.Dog;
import cn.willvi.bean.Pig;
import cn.willvi.selector.AnnoImportBeanDefinitionRegistrar;
import cn.willvi.selector.AnnoImportSelector; /**
* @Import注解的运用
* @author willvi
*
*/
@Configuration
//快速导入到容器内 输入的组件名称为全类名
//通过实现ImportSelector接口
//通过实现ImportBeanDefinitionRegistrar手工注册
@Import({Dog.class,AnnoImportSelector.class,AnnoImportBeanDefinitionRegistrar.class}) public class AnnoImportConfig { public static void main(String[] args) {
ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AnnoImportConfig.class);
String[] beanNames = annotationConfigApplicationContext.getBeanDefinitionNames();
for (String bean : beanNames) {
System.out.println(bean);
}
}
}
6. 通过实现FactoryBean注册组件
通过实现FactoryBean接口(工厂bean)通常用于整合第三方框架
接口实现:
package cn.willvi.bean;
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean<Pig>{
public Pig getObject() throws Exception {
return new Pig();
}
public Class<?> getObjectType() {
return Pig.class;
}
//是否单例
public boolean isSingleton() {
return true;
}
}
使用:
package cn.willvi.config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import cn.willvi.bean.MyFactoryBean;
import cn.willvi.bean.Pig;
/**
* 通过FactoryBean的实现注册
* @author willvi
*
*/
@Configuration
public class FactoryBeanConfig {
@Bean
public MyFactoryBean MyFactoryBean() {
return new MyFactoryBean();
}
public static void main(String[] args) {
ApplicationContext applicationContext= new AnnotationConfigApplicationContext(FactoryBeanConfig.class);
//获取的是MyFactoryBean中getObject()返回的实例
System.out.println(applicationContext.getBean("MyFactoryBean"));
//添加'&' 获取的是MyFactoryBean实例
System.out.println(applicationContext.getBean("&MyFactoryBean"));
}
}
小结
给容器注册组件的几种方式:
- 包扫描配合注解(`@Controller@Service@Repository@Component)[自己写的类]
- @Bean 导入第三方包的组件
- @Import
- 直接通过 @Import({Dog.class,Pig.class})
- 通过实现ImportSelector接口返回全类名数组 @Import({实现的类})
- 通过实现ImportBeanDefinitionRegistrar接口手工注册组件 @Import({实现的类})
- 通过实现FactoryBean接口(工厂bean)通常用于整合第三方框架
- 默认获取到的是FactoryBean的getObject()返回的对象
- 要获取当前工厂类对象需 添加
&
符号
Spring注解开发-全面解析常用注解使用方法之组件注册的更多相关文章
- Spring注解开发-全面解析常用注解使用方法之生命周期
本文github位置:https://github.com/WillVi/Spring-Annotation/ 往期文章:Spring注解开发-全面解析常用注解使用方法之组件注册 bean生命周期 ...
- spring boot之入门Controller常用注解
Controller常用注解 @Controller 处理http请求 @RestController Spring4之后新加的注解,原来返回json数据需要@ResponseBody配合@Cont ...
- 使用Spring boot开发RestFul 风格项目PUT/DELETE方法不起作用
在使用Spring boot 开发restful 风格的项目,put.delete方法不起作用,解决办法. 实体类Student @Data public class Student { privat ...
- Spring中Bean管理的常用注解
在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...
- Spring 的Bean管理的常用注解
属性注入的注解(使用注解注入的方式,可以不用提供set方法) @Value 用于注入普通类型 @Autowired 自动装配 :默认按类型进行装配 按名称注入 @Qualifier 强制使用名称注入 ...
- [Java 开发利器Lombok] 常用注解演示
在以往的对象模型编码时,我们需要写一大堆的get/set以及不同的构造函数等.Lombok为我们提供了一个非常好的插件形式. 在大多数的项目中,只需要使用到以下集中Annotation就足够了,如果需 ...
- Spring Boot在Controllder中常用注解
1.@RestController @RestController 相当于@Controller+@ResponseBody 注解如果使用@RestController 注解Controller 中的 ...
- 注解开发中的@Results注解使用
package com.hope.dao;import com.hope.domain.User;import com.sun.xml.internal.bind.v2.model.core.ID;i ...
- Spring cloud开发内存占用过高解决方法
https://blog.csdn.net/wanhuiguizong/article/details/79289986 版权声明:本文为博主原创文章,转载请声明文章来源和原文链接. https:// ...
随机推荐
- [原]SuperMap GIS(JavaScript) 拉框放大和缩小功能实现
版权声明:本文为博主原创文章,未经博主允许不得转载. var ZoomControl; /* * 拉框缩小 */ function ZoomOut(){ if(ZoomControl==null||Z ...
- 谈 Python 程序和 C 程序的整合 (转载)
http://www.ibm.com/developerworks/cn/linux/l-cn-pythonandc/ 概览 Python 是一种用于快速开发软件的编程语言,它的语法比较简单,易于掌握 ...
- maven多层项目配置
今天遇到一个maven项目有3个子项目的配置问题,一开始项目结构是混乱的,而且包引入不能正常解析. 主项目上右键,选择configure->configure and detect nested ...
- cloudera-scm-server启动时出现Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Could not open connection问题解决方法(图文详解)
问题现象 查看 [root@cmbigdata1 cloudera-scm-server]# pwd /var/log/cloudera-scm-server [root@cmbigdata1 clo ...
- 【CSS】 元素块与文字的各种居中解决方案
元素块的居中 首先有这样一个200*200px的元素块在界面内. 元素块的水平居中: 如果想要让其水平居中,则有三种方法: 第一种是知道屏幕的长宽,则根据计算,(屏幕宽X-元素块宽Y)/ 2的结果是元 ...
- Python对日期进行格式化
Python对日期进行格式化 把当前时间输出为2017-04-07 19:00:00.进入python交互命令行输入: > import datetime > currtime = dat ...
- 2.2、js基础---预解析和严格模式
一.语言特性 1.预解析:js会把变量的声明(仅仅是声明)提到顶部,但是不会突破作用域. alert(a);var a= 12; //结果,undefi ...
- idea maven install 卡住,无报错排查。
今天使用idea打包,执行install,看控制台日志,卡主了(意思是日志不继续在控制台输打印了,卡主了,也看不到错误),也没有报错,然后进行排查. 进入dos命令,进入到项目的根目录,使用 运行 m ...
- 阿里云两台服务器之间拷贝文件命令scp
参考:云栖社区 不同的Linux之间copy文件通常有4种方法 1.ftp 2.samba服务 3.sftp 4.scp 最简单的方法就是scp,可以理解为ssh管道下的cp命令 把当前一个文件cop ...
- net 记录controller Action耗时
可能有些时候需要记录Action的执行时间来优化系统功能,这时可以用过滤器来实现 第1个例子 using System; using System.Diagnostics; using System. ...