热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringIOC容器中的常用注解

SpringIOC容器中的常用注解@Configuration表示当前类是一个配置类@ConfigurationpublicclassMainConfig{}@Bean用来注入be

Spring IOC容器中的常用注解


@Configuration

表示当前类是一个配置类

@Configuration
public class MainConfig {
}

@Bean

用来注入bean对象,和在xml中的

@Configuration
public class MainConfig {

//在Bean标签中有一个value值 表示给book取一个别名
@Bean
public Book book(){
return new Book();
}
}

@ComponentScan

需要扫描的包。在@ComponentScan有许多的参数

@Value:指定扫描的包

@excludeFilters:指定扫描的时候按照规则排除哪些组件

@includeFilters:指定扫描的时候只扫描配置的组件

@Filter:过滤的规则,默认是Annotation类型,主要一下几种类型

ANNOTATION, //按照注解
ASSIGNABLE_TYPE,//按照给定类型
ASPECTJ,//按照aspectj,基本不怎么用
REGEX,//按照正则
CUSTOM;//按照自定义
//扫描类
@Configuration
@ComponentScan(value = "com.jack",includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes =
{MyFilterTye.class})},
useDefaultFilters = false)
public class ComponentScanConfig {
}
//自定义配置类
public class MyFilterTye implements TypeFilter {
/**
*
* @param metadataReader 当前类信息
* @param metadataReaderFactory 正在扫描类的信息
* @return
* @throws IOException
*/
@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);
if (className.contains("ok")){
return true;
}
return false;
}
}
//测试类
public class TestMain {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext annotatiOnConfigApplicationContext=
new AnnotationConfigApplicationContext(MainConfig.class);
Book bean = annotationConfigApplicationContext.getBean(Book.class);
String[] beanDefinitiOnNames= annotationConfigApplicationContext.getBeanDefinitionNames();
for (String name : beanDefinitionNames){
System.out.println(name);
}
}
}

@Scope

bean实例的作用域范围,默认在spring容器中是单例的

prototype:多实例,ioc容器在启动并不会取调用方法创建对象放在容器中,每次获取的时候才会调用方法取创建

singleton:单实例(默认值),ioc容器启动的会自动创建bean实例放到ioc容器中,以后每次获取bean实例直接从ioc容器中拿

//这个两个用的比较少,主要在浏览器请求的时候进行创建

request:同一次请求创建一个实例

session:同一个session创建一个实例


@Lazy

懒加载,在实例注入bean实例的时候,在启动容器的时候不进行创建实例,在第一调用的时候创建bean实例

@Configuration
public class MainConfig {

@Lazy
@Bean
public Book book(){
return new Book();
}
}

@Conditional

按照一定的条件进行判断,满足条件给容器注册bean

如果作用在方法上,对一个bean注册的条件过滤

如果在类上,表示对整个类进行条件过滤

//根据条件进行注册bean
@Configuration
@Import({ComponentScanConfig.class})
public class MainConfig {
@Bean
public Book book(){
return new Book();
}
@Conditional(LinuxCindition.class)
@Bean("book1")
public Book book1(){
return new Book("平凡的世界",92.1);
}
@Conditional(WindowsCondition.class)
@Bean("book2")
public Book book2(){
return new Book("简爱",90.0);
}
}
/**
* @description 判断是否是Linux系统
* @author: zq
* @create: 2021-07-21 22:51
**/
public class LinuxCindition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//1.获取ioc的BeanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment envirOnment= conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//判断操作系统
String property = environment.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}
}
//判断是否是windows系统
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//判断操作系统
//获取当前环境信息
Environment envirOnment= conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Windows")){
return true;
}
return false;
}
}
//在创建对象的时候会根据条件来进行创建

@Import

给容器导入一个组件,id就是组件的类名,比如导入三方包中的组件

@Import({ComponentScanConfig.class})

ImportSelector接口

返回值就是要导入到组件中的全类名

//实现ImportSelector接口
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.jack.bo.Blue","com.jack.bo.Yellow"};
}
}
在@import注解中添加MyImportSelector类
@Import({ComponentScanConfig.class,MyImportSelector.class})

ImportBeanDefinitionRegistrar接口

通过手动注册bean到容器中,使用方法和ImportSelector类似,实ImportBeanDefinitionRegistrar接口,然后通过Import注解注入到bean中


FactoryBean接口

作用:通过实现FactoryBean,可以对bean实例进行定制实例化的bean,简单的来说就是可以根据自己的需求对bean实例进行包装,注入到容器中。



  1. 默认获取的是工厂bean调用的getObject创建的对象

  2. 如果要获取bean本身,在id前加上&符号(&beanName)


Bean生命周期常用的注解


initMethod和destroyMethod

bean的初始化和销毁方法

在@Bean注解上initMethod和destroyMethod方法

初始化

​ 单例:是在对象创建完成,复制完成之后调用初始化方法,

销毁:

​ 单例:是在容器关闭的时候调用销毁方法

​ 多例:容器不会管理这个bean,容器不会调用销毁方法,需要进行手动销毁

@Bean(initMethod = "init",destroyMethod = "destory")
public Blue blue(){
return new Blue();
}

InitializingBean和DisposableBean接口

​ Bean通过实现InitializingBean和DisposableBean接口,都是初始化赋值和销毁

@Component
public class InitBean implements InitializingBean, DisposableBean {
public InitBean() {
System.out.println("创建一个InitBean");
}
@Override
public void destroy() throws Exception {
System.out.println("InitBean destroy=======");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitBean afterPropertiesSet=======");
}
}

@PostConstruct和@PreDestory注解

@PostConstruct:在bean实例创建赋值完成之后,进行初始化

@PreDestory:在容器移除bean的时候进行,进行调用

@Component
public class PostConstructorBean {
public PostConstructorBean() {
System.out.println("---》创建PostConstructorBean");
}
@PostConstruct
public void initPostConstructorBean(){
System.out.println("---》初始化initPostConstructorBean");
}
@PreDestroy
public void preDestroy(){
System.out.println("---> 销毁前调用preDestroy");
}
}

@BeanPostProcessor

Bean的后置处理器,在bean的初始化前后进行一些操作

postProcessBeforeInitialization:初始化前调用

postProcessAfterInitialization:初始化之后调用

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化前==MyBeanPostProcessor");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化厚==MyBeanPostProcessor");
return bean;
}
}

//源码解读
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//前置处理方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//后置处理方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}

BeanPostProcessor注解有很强大的功能,在Spring底层支持:

bean的赋值,注入其他组件,@Autowired注解,@Async异步注解等等都是通过BeanPostProcessor来的

image-20210723104058907


属性赋值注解


@Value

为属性进行赋值



  • 基本参数



  • 使用SpEL:#{}



  • 配置文件中取值:${}

    @Value("平凡的世界")
    private String name;
    @Value("#{20.2-10.1}")
    private Double price;
    @Value("${person.author}")
    private String author;



@PropertySource

加载properties配置文件,可以通过classpath或者file的方式加载

/**
* Indicate the resource location(s) of the properties file to be loaded.
* For example, {@code "classpath:/com/myco/app.properties"} or
* {@code "file:/path/to/file"}.
*

Resource location wildcards (e.g. **/*.properties) are not permitted;
* each location must evaluate to exactly one {@code .properties} resource.
*

${...} placeholders will be resolved against any/all property sources already
* registered with the {@code Environment}. See {@linkplain PropertySource above}
* for examples.
*

Each location will be added to the enclosing {@code Environment} as its own
* property source, and in the order declared.
*/
String[] value();
@PropertySource(value = {"classpath:/person.properties"})

@Autowired

自动注入依赖实例的值



  1. 默认优先按照类型去容器中找对应的组件,找到就赋值(applicationContext.getBean(BookDao.class))

  2. 如果按照类型找到多个,那么就按照属性的名去找(applicationContext.getBean(booKDao)

@Qualifier

指定需要封装的主键id,来注入属性

require

配和@Autowired使用,表示属性为非必须的

@Primary

在spring进行自动装配的时候,默认使用首先的bean;也可以使用@Qualifier指定继续使用哪个

@Service
public class BooKService {

@Qualifier("book1")
@Autowired(required = false)
private BooKDao booKDao2;
}

@Autowired可以使用在方法之上,但是获取值是获取ioc容器中的值

@Autowired可以使用在构造器上,获取值也是从ioc容器中获取 ,如果只有有参构造器,可以省略掉@Autowired注解

@Autowired可以使用在参数位置,获取值也是从ioc容器中获取


@Resource和@Inject

@Resource和@Inject是属于java中的注解规范,spring也是支持

@Resource:

​ 可以实现@Autowired一样的自动装配功能,默认按照组件的名称进行装配

​ 但是没有@Primary优先的和require的功能

@Inject:

​ 需要引入javax的包,和Autowired功能是一样的


自定义组件使用SPring容器底层的一些组件(ApplicationContext,BeanFactory,等等)

需要实现XXXAware接口,比如ApplicationContexAware接口等等

image-20210725171102224

public class Yellow implements ApplicationContextAware {

private ApplicationContext applicationContext;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicatiOnContext= applicationContext;
}
}

@Profile

指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境都不会被注册。

/*
在dev环境中会加载实例bean
*/
@Configuration
public class MainConfigOfProfile {
@Profile("dev")
@Bean
public Book Book(){
return new Book("111",90.1);
}
}


推荐阅读
  • 开发笔记:spring boot项目打成war包部署到服务器的步骤与注意事项
    本文介绍了将spring boot项目打成war包并部署到服务器的步骤与注意事项。通过本文的学习,读者可以了解到如何将spring boot项目打包成war包,并成功地部署到服务器上。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 带添加按钮的GridView,item的删除事件
    先上图片效果;gridView无数据时显示添加按钮,有数据时,第一格显示添加按钮,后面显示数据:布局文件:addr_manage.xml<?xmlve ... [详细]
  • 字符串匹配RabinKarp算法讲解
    问题描述:Rabin-Karp的预处理时间是O(m),匹配时间O((n-m1)m)既然与朴素算法的匹配时间一样,而且还多了一些预处理时间& ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文介绍了Hive常用命令及其用途,包括列出数据表、显示表字段信息、进入数据库、执行select操作、导出数据到csv文件等。同时还涉及了在AndroidManifest.xml中获取meta-data的value值的方法。 ... [详细]
  • 本文整理了Java中org.apache.hadoop.hive.ql.plan.ExprNodeColumnDesc.getTypeInfo()方法的一些代码示例,展 ... [详细]
  • 开发笔记:Spark Java API 之 CountVectorizer
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了SparkJavaAPI之CountVectorizer相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
新手村一霸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有