Springboot与各组件之间的整合(三)

@TOC

springboot中的条件注解

@Conditional
当触发特定条件时会装载该bean

该注解下有很多子注解,
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
@ConditionalOnClass

package org.springframework.boot.autoconfigure.condition;
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.context.annotation.Conditional;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnClassCondition.class})
public @interface ConditionalOnClass {
    Class<?>[] value() default {};

    String[] name() default {};
}

案例—>>>

@ConditionalOnClass(name="com.mysql.cj.jdbc.Driver")
    @Bean(value = "myUser")
    public User  User1(){
        return new User("李四",23);
    }

在这里插入图片描述
当修改为
com.mysql.cj.jdbc.DriverDatasource时,

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myUser' available
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:872)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1344)

在获取bean时会提示找不到该bean
@ConditionalOnClass(name=“aaa”)注解在类aaa加载时才会装配该bean,其实这也体现在源码中,比如我们导入thmeleaf时,会自动导入相关配置依赖

在这里插入图片描述
例如在没有引入freemarker时,
在springbootautoconfig中的配置类信息中可以看到

在这里插入图片描述
这说明有一些配置类没有加载进来,如果这时候我们导入freemarker,再次查看

在这里插入图片描述
说明当没有导入freemarker时,有关于freemarker的配置信息不会加载

同理其他的一些依赖也是如此;
但是这也会引发一个问题,就是我肯不想
@ConditionalOnProperty配置类:

package com.gavin.config;
import com.gavin.pojo.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * @author Gavin
 */
@Configuration(proxyBeanMethods = false)
@Import(value = {User.class} )
public class MyConfig {

    @Bean(value = "myUser")
    @ConditionalOnProperty(name = "server.port" ,havingValue = "8080")
//当配置中有server.port且值为8080时会加载这个bean
    public User  getUser(){
        return new User("张三",23);
    }

}

@SpringBootApplication
public class ZzyApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ZzyApplication.class, args);
        User getUser = context.getBean("myUser", User.class);
        System.out.println(getUser);

    }

}

在这里插入图片描述

如果类似的注解在类上,那么这表示配置类中的所有bean都会被加载,

@ConditionalOnProperty(name = "server.port" ,havingValue = "8080")
@Configuration(proxyBeanMethods = false)
@Import(value = {User.class} )
public class MyConfig {

那么就会产生一个问题----优先级的问题
类注解上有该注解,方法上也有注解;
发现当注解的信息名相同,但是值不同时,都会报错,即相同的配置只能有一个 ;

@ConfigureProperties
在这个注解案例之前先回顾一下之前装配数据的方式---->>@Value

@AllArgsConstructor
@NoArgsConstructor
@Data
@Component
public class User implements Serializable {
@Value("周三干")
    private String uName;
@Value("18")
    private Integer uAge;
    private static final long serialVersionUID = -1L;
}

在这里插入图片描述
通过配置文件进行bean的注入
我们知道,springboot在扫描配置文件的时候会扫描yml,yaml以及properties配置文件,所以我们可以通过.properties的方式来完成bean中属性数据的注入----这就需要依靠@ConfigureProperties来完成,

 
@Configuration
public class MyConfig {


application.properties文件

user.uName=zzy
user.uAge=29
package com.gavin.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @author Gavin
 */
@AllArgsConstructor
@NoArgsConstructor
@Data

@ConfigurationProperties(prefix = "user")//匹配前缀,一般习惯类的小写
@Component//注册bean
public class User implements Serializable {

//@Value("周三干")

    private String uName;
//@Value("18")

    private Integer uAge;
    private static final long serialVersionUID = -1L;
}

在这里插入图片描述
当然我们按照习惯会将注解添加到配置类上
则这时需要的注解有所改变---->>

@ EnableConfigurationProperties

package org.springframework.boot.context.properties;
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.context.annotation.Import;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({EnableConfigurationPropertiesRegistrar.class})
public @interface EnableConfigurationProperties {
    String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";

    Class<?>[] value() default {};
}

案例

@EnableConfigurationProperties(User.class)
public class MyConfig {


@AllArgsConstructor
@NoArgsConstructor
@Data
@Component
@ConfigurationProperties(prefix = "user")

public class User implements Serializable {

//@Value("周三干")

    private String uName;
//@Value("18")

    private Integer uAge;
    private static final long serialVersionUID = -1L;
}

小结—>>>如果在实体类上注解—>>
@Component//注册bean
@ConfigureProperties(prefix=“指定前缀”),
配置类上注解---->>>@Configuration
如果在配置类上,则实体类上
则只需要将配置类上注解换成@EnableConfigurationProperties(User.class)

在springboot中以xml方式引入bean(了解)

自己定义xml配置文件,在文件中配置bean,这需要在resources目录下准备一个xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.gavin.pojo.User">
        <property name="UName" value="李四五"/>
        <property name="UAge" value= '18'/>
    </bean>
</beans>

配置xml之后,还需要将扫描该文件,因为默认会扫描yml,yaml,properties文件,所以要通过注解来完成对xml文件的导入;

@Configuration
@ImportResource(value = "classpath:beans.xml")
public class MyConfig {

在这里插入图片描述
在这里插入图片描述
可以添加 @ComponentScan没有任何参数或使用 @SpringBootApplication隐式包含它的注释。 您的所有应用程序组件( @Component, @Service, @Repository, @Controller, and others) 被自动注册为 Spring Beans。

import org.springframework.stereotype.Service;
@Service
public class MyAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    public MyAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
    }

    // ...

}


如果一个 bean 有多个构造函数,你需要标记你希望 Spring 使用的那个

@Autowired:

import java.io.PrintStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MyAccountService implements AccountService {

    private final RiskAssessor riskAssessor;

    private final PrintStream out;

    @Autowired
    public MyAccountService(RiskAssessor riskAssessor) {
        this.riskAssessor = riskAssessor;
        this.out = System.out;
    }

    public MyAccountService(RiskAssessor riskAssessor, PrintStream out) {
        this.riskAssessor = riskAssessor;
        this.out = out;
    }

    // ...

}

springboot的 延迟初始化

SpringApplication允许延迟初始化应用程序。 当启用延迟初始化时,bean 会在需要时创建,而不是在应用程序启动期间创建。 因此,启用延迟初始化可以减少应用程序启动所需的时间。 在 Web 应用程序中,启用延迟初始化将导致许多与 Web 相关的 bean 在收到 HTTP 请求之前不会被初始化。

延迟初始化的一个缺点是它会延迟应用程序问题的发现。 如果配置错误的 bean 被延迟初始化,则在启动期间将不再发生故障,并且只有在 bean 初始化时问题才会变得明显。 还必须注意确保 JVM 有足够的内存来容纳应用程序的所有 bean,而不仅仅是那些在启动期间初始化的 bean。 由于这些原因,默认情况下不启用延迟初始化,建议在启用延迟初始化之前对 JVM 的堆大小进行微调。

可以使用以下方式以编程方式启用延迟初始化 lazyInitialization方法 SpringApplicationBuilder或者 setLazyInitialization方法 SpringApplication. 或者,可以使用 spring.main.lazy-initialization属性如下例所示:
特性
yaml

spring.main.lazy-initialization=true

如果禁用某些 bean 的延迟初始化,同时对应用程序的其余部分使用延迟初始化,您可以使用显式将它们的延迟属性设置为 false @Lazy(false)注解。

springboot的热插拔

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <version>2.6.3</version>
</dependency>

设置一下idea
在这里插入图片描述
设置registry
在这里插入图片描述

在这里插入图片描述

某些资源在更改时不一定需要触发重新启动。 例如,Thymeleaf 模板可以就地编辑。 默认情况下,更改资源 /META-INF/maven, /META-INF/resources, /resources, /static, /public, 或者 /templates不会触发重新启动,但会触发 实时重新加载 。 如果要自定义这些排除项,可以使用 spring.devtools.restart.exclude财产。 例如,仅排除 /static和 /public您将设置以下属性:
特性
yaml

spring.devtools.restart.exclude=static/,public/

如果要保留这些默认值并 添加 其他排除项,请使用 spring.devtools.restart.additional-exclude而是财产。 

Springboot的延迟初始化

SpringApplication允许延迟初始化应用程序。 当启用延迟初始化时,bean 会在需要时创建,而不是在应用程序启动期间创建。 因此,启用延迟初始化可以减少应用程序启动所需的时间。 在 Web 应用程序中,启用延迟初始化将导致许多与 Web 相关的 bean 在收到 HTTP 请求之前不会被初始化。

延迟初始化的一个缺点是它会延迟应用程序问题的发现。 如果配置错误的 bean 被延迟初始化,则在启动期间将不再发生故障,并且只有在 bean 初始化时问题才会变得明显。 还必须注意确保 JVM 有足够的内存来容纳应用程序的所有 bean,而不仅仅是那些在启动期间初始化的 bean。 由于这些原因,默认情况下不启用延迟初始化,建议在启用延迟初始化之前对 JVM 的堆大小进行微调。

可以使用以下方式以编程方式启用延迟初始化 lazyInitialization方法 SpringApplicationBuilder或者 setLazyInitialization方法 SpringApplication. 或者,可以使用 spring.main.lazy-initialization属性如下例所示:
特性
yaml

spring.main.lazy-initialization=true

如果您想禁用某些 bean 的延迟初始化,同时对应用程序的其余部分使用延迟初始化,您可以使用显式将它们的延迟属性设置为 false @Lazy(false)注解。 
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeMartain

祝:生活蒸蒸日上!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值