美文网首页
spring bean深入理解

spring bean深入理解

作者: 尤力 | 来源:发表于2020-01-20 12:44 被阅读0次

一、概述

我们知道,使用类的方法和属性,通常需要将类进行实例化后,才能具象化去使用这些方法和属性。

然而类的实例随着方法运行的结束结束,。这不仅增加了开发的代价,还需要大量的甚至重复的实例化代码,而且增加了GC回收的压力。那么是否可以通过一个容器来进行统一管理,在spring进行统一管理得这些对象就是bean。

二、bean的含义

Spring Bean是被实例的,组装的及被Spring容器管理的Java对象。

Spring容器会自动完成@bean对象的实例化。

通俗理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了。比如我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean或者给出一个Bean。

三、bean的三种配置方案

1、在XML中进行显示配置

2、使用Java代码进行显示配置

3、隐式的bean发现机制和自动装配

推荐方式:  3> 2> 1

四、bean的装配之自动化装配bean

1.组件扫描(组件扫描):Spring会自动发现应用程序。

组件注解作用:

表明该类会作为组件类。

不过,组件扫描默认是不开启用的,我们还需要显示配置下Spring,从而命令它去寻找带有@Component注解的类,并创建Bean。

bean配置好了需要收集这些bean,那么如何将这些bean收集起来呢? 此时,就需要bean的收集器,有两种方式,包括java和XML

Java代码执行bean收集:

其中,如果CompoentScan后面没有参数的话,则会扫描与配置类相同的包。

@Configuration

@ComponentScan

public class JavaConfig {

}

XML方式执行bean收集:

 <!-- 自动扫描该包 -->

 <context:component-scan base-package="com.**" />

当这些bean收集起来之后,当我们想要在某个测试类使用@Autowired注解来引入这些收集起来的bean时,只需要给这个测试类添加@ContextConfiguration注解来标注我们想要导入这个测试类的某些bean。

4.2、为组件扫描的bean命名

默认情况加,Spring应用上下文种所有的bean都会给定一个ID。在前面的例子中,尽管我们没有明确地为MailSender bean设置ID,但是Spring会默认为MailSender设置ID为mailSender,也就是将类名的第一个字母变成小写。

如果想为这个bean设置不同的ID,那就将期望的值传递给@Component注解

@Component("mailMessageSender")

public class MailSenderimplements IMessageSender {

@Override

    public void send() {

        System.out.println("this is mailsender!");

    }

}

4.3、设置组件扫描的基础包

前面再给MessageConfig类设置@ComponentScan,我们并没有设置任何属性,这个时候默认扫描默认包是:MessageConfig类所在包及其包的子包。

MessageConfig所在的包与@ComponentScan的扫描的包不在同一个包下,就需要设置扫描的包,否则不能进行依赖注入。

@Configuration

@ComponentScan(basePackages ="com.***")

    public class MessageConfig {

     }

}

4.4、通过为bean添加注解实现自动装配

如果所有的对象都是独立的,彼此之间没有任何依赖,那么使用组件扫描就能自动化装配bean。

但是实际工作中,很多对象会依赖其他对象完成任务。这时候就需要能够将组件扫描得到的bean和他们依赖装配在一起。这就是自动装配(autowiring)

使用Spring的Autowired

@Component

public class AppOptimize implements IOptimizePerformance {

    private IMessageSendermessageSender;

    @Autowired

    public AppOptimize(IMessageSender messageSender) {

        this.messageSender = messageSender;

    }

    @Override

     public void optimize() {

            System.out.println("app 优化之异步消息发送");

            messageSender.send();

    }

}

AppOptimize类的构造器上添加了@Autowired注解,表明当Spring创建AppOptimize bean的时候,会通过这个构造器来进行实例化。

Autowired的多种方式

1、构造器注解(constructor)

2、属性setter注解

3、field注解

不管使用上面3中的哪个方法,Spring都会满足声明的依赖。假如有且只有一个bean匹配依赖的话,那么这个bean将会被装配进来。

如果使用2,3方式注解,有多个bean的话,则用Qualifier指定。

比如:优化包含后端优化的实现和前端优化实现。

@Autowired

//@Qualifier("appOptimize")

private IOptimizePerformance  appOptimize;  //指定具体的实现

@Autowired

 @Qualifier("appOptimize") //使用Qualifier指定具体使用到哪个bean

private IOptimizePerformance  optimize;

如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,可以使用

@Autowired(required = false)

private IOptimizePerformance  appOptimize;

required=false表示如果没有匹配的话,Spring会让bean处于未装配的样子。使用未装配的属性,会出现NullPointerException

总结:

所以在使用开发的时候一般建议使用Resource(package javax.annotation)进行注解。但是Resource不支持构造器注解

五、bean的装配之Java代码装配Bean

尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化更为推荐,但是有时候行不通。比如引用第三方组件,没办法在它的类上添加@Component及@Autowired。

所以就需要JavaConfig或者XML配置

在进行显示配置的时候,JavaConfig是更好的解决方案。

JavaConfig与其他的Java代码又有所区别,在概念上它与应用程序中的业务逻辑和领域代码又有所不同。JavaConfig是配置相关代码,不包含任何逻辑代码。通常将JavaConfig放到单独的包中。

@Configuration

public class RedisConfig {

}

使用@Configuration表明RedisConfig是一个配置类

1、用 配置 代替 扫描。

之前:

@Configuration

@ComponentScan(basePackages ="com.nrsc.springstudy.bean_di")

public class MessageConfig {

  }

}

如果去掉@ComponentScan(basePackages ="com.nrsc.springstudy.bean_di") 就会出现BeanCreationException异常。

现在解决方案:

声明简单的bean

在MessageConfig中声明bean,需要编写一个方法,该方法会创建所需类型的实例,然后这个方法添加 @Bean注解

@Bean

public IMessageSender setMessageSender(){

return new MailSender();

}

@Bean注解会告诉Spring这个方法会返回一个对象,该对象要注册为Spring应用上下文中的bean。

默认情况下,bean的ID与带有 @Bean注解的方法名是一样的,在上面的例子中,bean的ID将会是setMessageSender。如果想设置不同的ID,那么可以重命名该方法,也可以通过name属性指定一个不同的名字:

@Bean("messageSender")

public IMessageSender setMessageSender(){

return new MailSender();

}

借助JavaConfig实现注入

前面声明的IMessageSender很简单,因为没有其他依赖。但现在,我们需要声明IOptimizePerformance bean,它依赖于IMessageSender。

在javaConfig中装配bean的最简单方式就是引用创建bean的方法。

@Bean

public IOptimizePerformance frontOptimize() {

return new FrontOptimize(setMessageSender());

}

六、bean的装配之通过XML装配Bean

该装配不进行详解,使用较少。

附:

重要注解及其作用

@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境

@ContextConfiguration 作用:加载配置文件。Spring整合JUnit4测试时,使用注解引入多个配置文件

单个文件 

@ContextConfiguration(Locations="classpath:applicationContext.xml")  

@ContextConfiguration(classes = SimpleConfiguration.class)

多个文件时,可用{}

@ContextConfiguration(locations = { "classpath:spring1.xml", "classpath:spring2.xml" }) 

@Component :当一个类添加了注解@Component,那么他就自动变成了一个bean,就不需要再Spring配置文件中显示的配置了。

@Qualifier(""):多个bean实现同一个接口的话,指定具体使用哪一个bean。

@Autowired(required = false)

相关文章

网友评论

      本文标题:spring bean深入理解

      本文链接:https://www.haomeiwen.com/subject/cvfdzctx.html