栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot组件添加详细解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot组件添加详细解析

2.1、组件添加

1、@Configuration(不懂看下面文字描述)

  • 基本使用
  • Full模式与Lite模式
    • 示例
    • 最佳实战
      • 配置 类组件无依赖关系用Lite模式(@Configuration(proxyBeanMethods = false))加速容器启动过程,减少判断
      • 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式(@Configuration(proxyBeanMethods = true))

怎么给容器里添加组件

准备了俩个类:

User.java

package com.chentianyu.boot.bean;


public class User {
    private Integer age;
    private String name;

    public User(){}
    public User(Integer age , String name){
        this.age = age;
        this.name = name;
    }

    public Integer getAge(){return age;}
    public void setAge(Integer age){this.age = age;}

    public String getName(){return name;}
    public void setName(String name){this.name = name;}

    public String toString(){
        return "User{" +
                "name = " + name +
                ", age = " + age +
                "}";
    }
}

Pet.java

public class Pet {
    private String name;
    
    public Pet(){}
    public Pet(String name){this.name = name;}
    
    public String getName(){return name;}
    public void setName(String name){this.name = name;}
    
    public String toString(){
        return "Pet{" + 
                "name = " + name + ''' + 
                "}";
    }
}

如果用以前原生的Spring得:

resources -> new -> XML Configuration File -> Spring Config -> beans.xml


    
        
        
        
    
    

    
        
    

这是以前用springxml形式

springboot不是这种xml形式,springboot怎么给容器中添加组件

第一种:

springboot不写配置文件了在springboot底层可以使用@Configuration注解

package com.chentianyu.boot.config;

import org.springframework.context.annotation.Configuration;

@Configuration//告诉SpringBoot这是一个配置类(把这个类说明@Configuration类似于告诉spring这个文件是配置文件)
public class MyConfig {//这就等于创建了一个文件(beans.xml)
}

我们虽然不能写标签了,但是能写方法:

@Bean //给容器中添加组件。以方法名作为组件的id,返回类型就是组件类型。返回的值,就是组件在容器中的实例(我们不用标签,我们用@Bean注解)
public User user01(){
	return new User(18, "lisi");
}

不想方法名作为组件名:

@Bean("名字")

验证:在主程序中:

MainAppliction.java

//从容器中获取组件
run.getBean(组件名,组件的类型);
例如:
Pet tom01 = run.getBean("tom",Pet.class);

是不是单实例(验证):

System.out.println("组件:" + (tom01 == tom02));
组件:true

注册的组件就是单实例的

 
   

验证MyConfig.java是否是一个组件:

MyConfig bean = run.getBean(MyConfig.class);
System.out.println(bean);

结果:

com.chentianyu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$1edd5731@286b39c2

最大的特性:在SpringBoot2.0以后的版本里多了一个boolean proxyBeanMethods() default true;是基于Spring5.2以后多的属性:

Configuration.java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;//默认是true
}
@Configuration(proxyBeanMethods = true)

proxyBeanMethods:代理Bean的方法

我们这个bean配置类里面申明过User和Pet俩个方法,能不能调用配置类的俩个方法:

bean.user01();

我们把配置类的user01()方法多调用几遍,会不会得到不一样的对象?

配置类它的作用就是这个user01()方法是给容器中添加组件的(我们使用@Bean标注了)但是我们在外部把这个user01()方法多调了俩遍,那我们这个方法返回的这个对象是从容器中拿呢?还是就是普通的调用方法?

答案是true

也就是说我们配置类里面一旦组件注册的这个方法,你在外面调用多少遍,它都是拿到容器中的那个实例

    @Bean //我们不用标签,我们用@Bean注解
    public User user01(){
        return new User(18, "lisi");
    }

相等的原因就是我们proxyBeanMethods属性。

我们这个proxyBeanMethods属性说这个方法会不会被代理,默认会(true),会的情况下我们就看到我们容器(MyConfig)获取到我们组件的这个对象。MyConfig本身就不是一个普通的对象(com.chentianyu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$7ab85b6@4905c46b)它是我们这个EnhancerBySpringCGLIB相当于被SpringCGLIB增强了的代理对象。

//这里获取到的本身就是代理对象
MyConfig bean = run.getBean(MyConfig.class);

代理对象调用user01()我们springboot里面的默认逻辑就是:如果@Configuration(proxyBeanMethods = true)是true , 我们这个类获取到的就是代理对象。调用方法。我们springboot就会默认检查容器中有没有这个方法以及返回的组件如果有就拿,如果没有就调用新创

//@Configuration(proxyBeanMethods = true)代理对象调用方法。springboot总会检查这个组件是否存在于容器中
//保持组件单实例
User user01 = bean.user01();

如果@Configuration(proxyBeanMethods = false)呢?

我们从容器中拿到(getBean())的这个对象类型是什么类型?

我们发现拿到的类型不再是代理对象(com.chentianyu.boot.config.MyConfig$$EnhancerBySpringCGLIB$$7ab85b6@4905c46b)而是com.chentianyu.boot.config.MyConfig@2adddc06。User user01 = bean.user01();多次调用方法就不是true相等的值。

这个就衍生出了:SpringBoot在底层@Configuration的俩个配置:一个是Full(全配置@Configuration(proxyBeanMethods = true))和Lite(轻量级配置@Configuration(proxyBeanMethods = false))。也就是说以后我们想要给容器中添加组件的时候,我们编写一个配置类,然后如果我们proxyBeanMethods为true的情况下,我们配置类每一个给容器中每一个给组件注册的方法,在外边随便调用,它都会从容器中找组件;但是如果proxyBeanMethods为false的情况下,我们MyConfig配置类再也不会保存代理对象,你在外边无限次调用这个方法,每一次调用都会产生一个新的方法(new User(18,"lisi"))。

这个来解决什么场景呢?

组件依赖

举个例子:

有一个User.java

package com.chentianyu.boot.bean;


public class User {
    private Integer age;
    private String name;
    
    private Pet pet;//假设用户要养一个宠物

    public User(){}
    public User(Integer age , String name){
        this.age = age;
        this.name = name;
    }

    public Integer getAge(){return age;}
    public void setAge(Integer age){this.age = age;}

    public String getName(){return name;}
    public void setName(String name){this.name = name;}
    
    public Pet getPet(){return pet;}
    public void setPet(Pet pet){this.pet = pet;}

    public String toString(){
        return "User{" +
                "name = " + name +
                ", age = " + age +
            	", pet = " + pet +
                "}";
    }
}

在MyConfig.java中我们的用户想要用我们容器中之前注册的这个tomcatPet()方法(宠物),那如果我调成@Configuration(proxyBeanMethods = false)模式,因为:

@Bean //我们不用标签,我们用@Bean注解
public User user01(){
	User lisi = new User(18, "lisi");
    lisi.setPet(tomcatPet());
    retrun lisi;
}

但是如果是@Configuration(proxyBeanMethods = true)模式的话,这个依赖就是成立的,我们用户(lisi)用的这个宠物(setPet())跟容器中用的宠物一模一样说明我们User组件依赖了tomcatPet组件。

测试:

User user01 = run.getBean("user01",User.class);
Pet tom = run.getBean("tom",Pet.class);

System.out.println("用户的宠物:" + (user01.getPet() == tom);

在@Configuration(proxyBeanMethods = true)情况下为true:用户的宠物就是容器里的宠物。

但如果是@Configuration(proxyBeanMethods = false)现象是:我这个用户想要用的宠物,我们把人家的方法调一遍,但这个方法又不是经过代理的,相当于这个方法直接调,它又帮我们new了一个宠物,虽然宠物的名字都是tomcat , 但是不是容器中的宠物。

springboot最大的更新

我们Lite模式(轻量级配置@Configuration(proxyBeanMethods = false))就是说调成false的优点是说我们SpringBoot不会来检查我们这个方法返回的值在容器(@Bean)中有没有,跳过检查,springboot直接启动,运行起来就非常快;调成true你每一次外界对它的调用它都会检查容器中是否有。

*Full和Lite最佳实战:

如果我们对容器中单单注册组件,别人也不依赖这些组件我们一般都调成false这样我们springboot启动起来会非常快加载起来也特别快;如果我们的这个组件明显下面还要用、还要依赖我们就把proxyBeanMethods调成true保证它依赖的组件就是容器中的组件


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/458609.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号