首页 > 其他分享 >20220704 Spring 相关

20220704 Spring 相关

时间:2022-11-28 09:56:06浏览次数:59  
标签:20220704 name Spring springframework 方法 Bean org 相关 new

@Configuration(proxyBeanMethods = false) 的作用

默认 proxyBeanMethods = true ,会为配置类生成 CGLIB 代理类。注意,不是为定义的 @Bean 生成代理类。

如果在 @Bean 方法 1 中引用了其他 @Bean 方法 2,此时需要被引用的 @Bean 方法 1 所在的配置类是代理类,对 @Bean 方法 2 所在的配置类不做要求

javadoc

指定是否应该代理 @Bean 方法以强制执行 bean 生命周期行为,例如即使在用户代码中直接调用 @Bean 方法的情况下,也可以返回共享的单例 bean 实例。

此功能需要方法拦截,通过运行时生成的 CGLIB 子类实现,该子类具有配置类及其方法不允许声明 final 等限制。

默认值为 true,允许通过配置类中的直接方法调用以及对此配置的 @Bean 方法的外部调用进行“bean 间引用”,例如从另一个配置类。

如果不需要这样做,因为每个特定配置的 @Bean 方法都是自包含的,并且设计为容器使用的普通工厂方法,请将此标志切换为 false 以避免 CGLIB 子类处理。

关闭 bean 方法拦截有效地单独处理 @Bean 方法,就像在非 @Configuration 类上声明时一样,也就是“@Bean Lite 模式”(参见 @Bean 的 javadoc)。因此,它在行为上等同于删除 @Configuration 构造型。

引入 @Bean 的方式

  • @Import
  • @ImportResource
    • 引入 XML 配置
  • @Bean
  • @Component 及其派生注解
    • 派生 @Configuration
    • 相关 @ComponentScan
  • ImportSelector 接口
    • 子接口 DeferredImportSelector
  • ImportBeanDefinitionRegistrar 接口

@AliasFor

在扫描 Bean 定义时被解析

AnnotationTypeMapping#resolveAliasTarget(java.lang.reflect.Method, org.springframework.core.annotation.AliasFor, boolean)

用法参考:

  • @SpringBootApplication

  • @Bean

DataBinder

参考资料

Javadoc

允许在目标对象上设置属性值的绑定器,包括对验证和绑定结果分析的支持。

可以通过指定允许的字段模式、必填字段、自定义编辑器等来自定义绑定过程。

警告:数据绑定可能会通过暴露不应被外部客户端访问或修改的部分对象图而导致安全问题。因此,数据绑定的设计和使用应考虑安全性。有关详细信息,请参阅参考手册中有关 Spring Web MVC 和 Spring WebFlux 的数据绑定的专门部分。

绑定结果可以通过 BindingResult 接口检查,扩展 Errors 接口:参见 getBindingResult() 方法。缺少的字段和属性访问异常将被转换为 FieldErrors,收集在 Errors 实例中,使用以下错误代码:

  • Missing field error: "required"

  • Type mismatch error: "typeMismatch"

  • Method invocation error: "methodInvocation"

默认情况下,绑定错误通过 BindingErrorProcessor 策略解决,处理缺失字段和属性访问异常:请参阅 setBindingErrorProcessor 方法。如果需要,您可以覆盖默认策略,例如生成不同的错误代码。

之后可以添加自定义验证错误。您通常希望将此类错误代码解析为适当的用户可见错误消息;这可以通过 org.springframework.context.MessageSource 解析每个错误来实现,它能够通过 org.springframework.context.MessageSource.getMessage(org.springframework.context.MessageSourceResolvable, java.util.Locale 方法解析 ObjectError / FieldError 。消息代码列表可以通过 MessageCodesResolver 策略自定义:见 setMessageCodesResolver 方法。 DefaultMessageCodesResolver 的 javadoc 说明了有关默认解析规则的详细信息。

此通用数据绑定器可用于任何类型的环境。

源码说明

实现了 PropertyEditorRegistry , TypeConverter 接口

通过委托模式实现接口方法

    protected PropertyEditorRegistry getPropertyEditorRegistry() {
        if (getTarget() != null) {
            return getInternalBindingResult().getPropertyAccessor();
        }
        else {
            return getSimpleTypeConverter();
        }
    }

    protected TypeConverter getTypeConverter() {
        if (getTarget() != null) {
            return getInternalBindingResult().getPropertyAccessor();
        }
        else {
            return getSimpleTypeConverter();
        }
    }

包含字段:

    @Nullable
    private AbstractPropertyBindingResult bindingResult;

    @Nullable
    private SimpleTypeConverter typeConverter;

Validator 相关,绑定时,会进行校验


AttributeAccessor

org.springframework.core.AttributeAccessor

public interface AttributeAccessor {

    void setAttribute(String name, @Nullable Object value);

    @Nullable
    Object getAttribute(String name);

    // 如果根据 name 可以获取到值,不再调用 computeFunction
    default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
        Assert.notNull(name, "Name must not be null");
        Assert.notNull(computeFunction, "Compute function must not be null");
        Object value = getAttribute(name);
        if (value == null) {
            value = computeFunction.apply(name);
            Assert.state(value != null,
                    () -> String.format("Compute function must not return null for attribute named '%s'", name));
            setAttribute(name, value);
        }
        return (T) value;
    }

    @Nullable
    Object removeAttribute(String name);

    boolean hasAttribute(String name);

    String[] attributeNames();

}

PropertyValue

org.springframework.beans.PropertyValue

保存单个 bean 属性的信息和值的对象。在此处使用对象,而不是仅将所有属性存储在以属性名称为键的映射中,可以提供更大的灵活性,并能够以优化的方式处理索引属性等。

请注意,该值不需要是最终所需的类型: BeanWrapper 实现应该处理任何必要的转换,因为该对象不知道将应用到的对象的任何信息。

实现类

  • AttributeAccessorSupport :内部存储是 LinkedHashMap

    private final Map<String, Object> attributes = new LinkedHashMap<>();
    
  • BeanMetadataAttributeAccessor :继承 AttributeAccessorSupport

    • 增加字段 source

    • 增加了自己的一些方法,使属性值都是 BeanMetadataAttribute

      • BeanMetadataAttribute :包含字段 namevaluesource
  • PropertyValue :继承 BeanMetadataAttributeAccessor

    • 增加字段 namevaluesource

    • 增加字段 convertedconvertedValueconversionNecessaryresolvedTokens

PropertyValues

接口,表示可遍历的 PropertyValue

实现类 MutablePropertyValues

BeanWrapper

唯一实现类 BeanWrapperImpl

通过 BeanPropertyBindingResultDataBinder 关联

DataBinder#getPropertyAccessor 返回的就是 BeanWrapperImpl ,在 DataBinder#applyPropertyValues 方法中通过 BeanWrapperImpl 设置属性值

        MyBean1 myBean1 = new MyBean1(1, "n1", new Date());
        Map<String, Object> map = new HashMap<>();
        map.put("name", "update name");
        MutablePropertyValues propertyValues = new MutablePropertyValues(map);

        DataBinder dataBinder = new DataBinder(myBean1);
        dataBinder.bind(propertyValues);

        System.out.println(myBean1);

        BindingResult bindingResult = dataBinder.getBindingResult();
        BeanPropertyBindingResult beanPropertyBindingResult = (BeanPropertyBindingResult) bindingResult;

        ConfigurablePropertyAccessor propertyAccessor = beanPropertyBindingResult.getPropertyAccessor();
        BeanWrapper beanWrapper = (BeanWrapper) propertyAccessor;

Spring 怎么读取 Bean 定义的

注册方法:org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

示例

public class MyMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(MyMain.class);
        for (String beanDefinitionName : annotationConfigApplicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }

    @Bean
    public MyBean1 myBean1() {
        return new MyBean1(1, "m1", new Date());
    }
}

输出结果:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myMain
myBean1

注册 internal 的代码路径:

AnnotationConfigServletWebServerApplicationContext()
    this.reader = new AnnotatedBeanDefinitionReader(this);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

实例化 AnnotatedBeanDefinitionReader 时注册了 internal

注册 myMain 的代码路径:

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class<?>...)
    register(componentClasses);

注册 MyBean1 的代码路径:

AbstractApplicationContext#refresh
    invokeBeanFactoryPostProcessors(beanFactory);
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
                postProcessor.postProcessBeanDefinitionRegistry(registry);
                    ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
                        ConfigurationClassPostProcessor#processConfigBeanDefinitions
                            this.reader.loadBeanDefinitions(configClasses);

这里的 readerConfigurationClassBeanDefinitionReader

ConfigurationClassPostProcessor#processConfigBeanDefinitions

判断是否为配置类

ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)
    ConfigurationClassUtils#isConfigurationCandidate

如果类上注解了 @Component@ComponentScan@Import@ImportResource ,或者类中存在 @Bean 注解的方法

@Configuration 也属于 @Component 的派生注解

ImportBeanDefinitionRegistrar 接口进行了处理

Spring Boot 怎么读取 Bean 定义的

Spring 类似,同样是实例化 AnnotatedBeanDefinitionReader 时,注册了 internal ,使用 reader 注册了 source ,然后在 ConfigurationClassPostProcessor 中进行扫描注册

使用 BeanDefinitionLoader 作为使用 AnnotatedBeanDefinitionReader 的中间类

标签:20220704,name,Spring,springframework,方法,Bean,org,相关,new
From: https://www.cnblogs.com/huangwenjie/p/16931406.html

相关文章

  • Spring Scheduled 三种定时方式
    SpringSchedule配置时间的三种方式fixRate:间隔时间,会根据首次执行时间预先安排固定的时间,错过立即执行fixDelay:间隔时间,上次结束时间后多少间隔后执行cron:指定......
  • springCloud将http请求网关更改为https请求
    如果需要将http请求换成https请求,大致需要三步。第一步:生成证书。网上有很多通过阿里云生成证书的教程。也有通过JDK生成证书。在jdk目录打开命令窗口,执行一下命令:keytoo......
  • SpringBoot整合MybatisPlus实现分页功能
    首先,展示一下项目的主题:  创建数据库,放入一些数据,方便我们接下来的功能演示: 接下来,我们创建一个实体类,然后写对应的接口:packagecom.example.domain;importlo......
  • SpringSecurity从入门到精通
    0.简介SpringSecurity和Shiro比较。中大型的项目都是使用SpringSecurity做安全框架,小项目使用Shiro比较多,因为它比SpringSecurity上手更加简单认证与授权:认证:验证......
  • springBoot 过滤器去除请求参数前后空格(附源码)
    背景:用户在前端页面中不小心输入的前后空格,为了防止因为前后空格原因引起业务异常,所以我们需要去除参数的前后空格!如果我们手动去除参数前后空格,我们可以这样做@......
  • SpringBoot(四):java从配置文件中取值的方式
    一、SpringBoot项目中取yaml配置文件中的值application.yamltest:url:localhost:8080name:rootpassword:123456val:a:1b:2c:3TestC......
  • SpringBoot17(项目部署)
    一、大纲二、操作过程1-(启一个web项目,已经配置好Maven的,按图片步骤点击package)2-(如果打包成功后的效果,Maven一定要配置好)2.1-Bulidingjar:打包后jar包的"位置/路径......
  • Spring Security(6)
    您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~Spring Security使用MySQL保存cookie记录虽然方便,但是目前更多的主流互联网应用都是用NoSQL来保存非业务数据的,SpringSe......
  • Spring Security(6)
    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~ Spring Security使用MySQL保存cookie记录虽然方便,但是目前更多的主流互联网应用都是用NoSQL来保存非业务数据的,Spring......
  • springboot的基本使用
    SpringBoot简介SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。使用了Spring框架后已经简化了我们的开发,而SpringBoot......