spring-接口大全

1. InitializingBean

1. 简介

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。

2. 使用

demo

@Component
public class MyInitBean implements InitializingBean {

    public void afterPropertiesSet() throws Exception {
        System.out.println("这是一个 InitializingBean 执行。。。。。");
    }
}

https://blog.csdn.net/qq_37705525/article/details/124808168

2. FactoryBean

1. 简介

FactoryBean 是 Spring 框架中的一个接口,它可以创建和管理其他对象的实例。通过实现 FactoryBean 接口,可以自定义对象的创建过程。

2. 使用

FactoryBean 源码
public interface FactoryBean<T> {
    
    // 获取由此工厂创建的对象实例
    T getObject() throws Exception;

    // 获取由此工厂创建的对象实例的类型
    Class<?> getObjectType();

    // 判断由此工厂创建的对象实例是否为单例模式
    default boolean isSingleton() {
        return true;
    }
}

示例:

@Component
public class MyInitBean implements FactoryBean<Dog> {

    public Dog getObject() throws Exception {
        return new Dog();
    }

    public Class<?> getObjectType() {
        return Dog.class;
    }

    public boolean isSingleton() {
        return true;
    }
}

其实会生成两个 Bean,此时根据名称 myInitBean 获取的是 Dog 实例,根据 &myInitBean 获取的才是 MyInitBean 实例。

https://blog.csdn.net/wangshuai6707/article/details/130717923

3. BeanFactoryPostProcessor

1. 简介

  • BeanFactoryPostProcessor的执行是Spring Bean生命周期非常重要的一部分;
  • BeanFactory级别的后置处理器,在Spring生命周期内,org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory只会执行一次;
  • 允许在容器读取到Bean的BeanDefinition数据之后,bean未实例化前,读取BeanDefiniion数据,并且可以根据需要进行修改;

2. 使用

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
        BeanDefinition dog = factory.getBeanDefinition("dog");
        MutablePropertyValues propertyValues = dog.getPropertyValues();
        propertyValues.add("name", "pz");
    }
}

4. BeanDefinitionRegistryPostProcessor

1. 简介

  • postProcessBeanDefinitionRegistry()方法可以通过BeanDefinitionRegistry对BeanDefintion进行增删改查;
  • 继承了BeanFactoryPostProcessor,BeanFactoryPostProcessor是容器级别的扩展接口,org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory方法在容器实例化后、刷新容器前被执行,即在容器刷新前还可以对BeanDefintion再作一些操作;

  总结起来就是,在所有的BeanDefinition加载完成之后,Bean真正被实例化之前,可以通过实现BeanDefinitionRegistryPostProcessor接口,对BeanDefinition再做一些定制化的操作,比如修改某个bean的BeanDefinition的属性、手动注册一些复杂的Bean。

2. 使用

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        //手工定义一个beanDefinition实例
        RootBeanDefinition beanDefinition = new RootBeanDefinition();

        //给beanDefinition填充属性
        beanDefinition.setBeanClass(Dog.class);
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        PropertyValue propertyValue1 = new PropertyValue("name", "旺财");
        PropertyValue propertyValue2 = new PropertyValue("color", "黑色");
        PropertyValue propertyValue3 = new PropertyValue("age", 17);
        propertyValues.addPropertyValue(propertyValue1);
        propertyValues.addPropertyValue(propertyValue2);
        propertyValues.addPropertyValue(propertyValue3);
        beanDefinition.setPropertyValues(propertyValues);

        //注册手工定义的beanDefinition
        registry.registerBeanDefinition("dog", beanDefinition);
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //根据类名取出手工注册的beanDefinition
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dog");
        System.out.println(beanDefinition.getBeanClassName());
        //根据类从容器中取出手工注册的beanDefinition所描述的实例bean
        Dog dog = beanFactory.getBean(Dog.class);
        System.out.println(this.getClass() + "-" + dog);

        dog.setName("peizhen");
    }
}

5. ImportBeanDefinitionRegistrar

1. 简介

  描述:ImportBeanDefinitionRegistrar接口是也是spring的扩展点之一,它可以支持我们自己写的代码封装成BeanDefinition对象,注册到Spring容器中,功能类似于注解@Service @Component。

  很多三方框架集成Spring的时候,都会通过该接口,实现扫描指定的类,然后注册到spring容器中,比如Mybatis中的Mapper接口,springCloud中的FeignClient接口,都是通过该接口实现的自定义注册逻辑。

2. 使用

1. 简单使用

一个 pojo 类

@Data
public class Dog {
    private String name;
    private Integer age;
    private String color;

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", color='" + color + '\'' +
                '}';
    }
}

实现 ImportBeanDefinitionRegistrar 接口

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata am, BeanDefinitionRegistry registry) {
        //1、通过Bd工具类生成bd对象,只是这个Db对象比较纯洁没有绑定任何类
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
        GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();
        //2、设置bd绑定的类型
        beanDefinition.setBeanClass(Dog.class);
        //3、注册到spring容器中
        registry.registerBeanDefinition("myDog",beanDefinition);
    }
}

使用 @Import 注入

@SpringBootApplication
@Import(MyImportBeanDefinitionRegistrar.class)
public class StartMain {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(StartMain.class, args);
        Dog dog = run.getBean(Dog.class);
        System.out.println(dog);
    }
}

这样效果就相当于 @Service、@Component 注解

6. ObjectProvider

ObjectProvider 是在 Spring 4.3 版本引入的一个接口,用于在Spring框架中获取对象实例。

使用示例:

package com.demo.component;

import com.demo.pojo.Dog;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

@Component
public class ObjectProviderComponent {

    //注入 ObjectProvider 对象
    @Autowired
    private ObjectProvider<Dog> dogObjectProvider;

    /**
     * 获取此类型可用 bean,没有或者多个都抛异常
     * */
    public void getObject(){
        //获取实例对象, 没有就报错
        Dog object = dogObjectProvider.getObject();
        System.out.println(object);
    }

    /**
     * 获取此类型可用 bean,没有返回 null,多个抛异常
     * */
    public void getIfAvailable(){
        //获取实例对象,不存在返回 null
        Dog ifAvailable = dogObjectProvider.getIfAvailable();
        System.out.println(ifAvailable);

        //获取实例对象,不存就创建一个
        Dog ifAvailable1 = dogObjectProvider.getIfAvailable(() -> new Dog("wpz", "pink", 30));
        System.out.println(ifAvailable1);
    }

    /**
     * 如果此类型 bean 有一个或者多个,就返回 null
     * */
    public void getUnique(){
        //获取唯一对象
        Dog ifUnique = dogObjectProvider.getIfUnique();
        System.out.println(ifUnique);

        //获取唯一对象,没有就创建一个
        Dog ifUnique1 = dogObjectProvider.getIfUnique(() -> new Dog("wpz", "pink", 29));
        System.out.println(ifUnique1);
    }

    /**
     * 以流的方式获取此类型 bean
     * */
    public void stream(){
        List<Dog> collect = dogObjectProvider.stream().collect(Collectors.toList());
        System.out.println(collect);
    }
}

7. Aware

Spring框架中的Aware接口主要用于让Bean在初始化时能够获取到Spring容器提供的某些特定服务或上下文信息,从而使Bean具有对Spring容器环境的感知能力。

Aware 接口本身没有任何方法,属于标记接口,可以通过子接口获取不同的用途。
常用的Aware接口及其用途:

  1. BeanNameAware: 允许Bean知道自己的名称(即在配置文件或注解中定义的Bean ID)。通过实现setBeanName(String beanName)方法,Bean可以获得其在Spring容器中的名称。

  2. BeanFactoryAware: 提供给Bean访问Spring容器的BeanFactory。通过实现setBeanFactory(BeanFactory beanFactory)方法,Bean可以获取到BeanFactory的引用,进而有能力访问容器中的其他Bean或执行Bean工厂级别的操作。

  3. ApplicationContextAware: 这是最常用的之一,它允许Bean获得Spring的ApplicationContext(应用上下文)。通过实现setApplicationContext(ApplicationContext applicationContext)方法,Bean能够访问到容器中的所有服务,包括消息解析、事件发布、资源加载等。

  4. ResourceLoaderAware: 允许Bean访问ResourceLoader,从而能够加载外部资源,如文件或类路径资源。

  5. EnvironmentAware: 使Bean能够访问到Environment对象,进而获取到应用的运行环境配置信息,如属性文件中的配置值。

  6. MessageSourceAware: 使得Bean能够访问到MessageSource,用于国际化和本地化的消息处理。

BeanFactoryAware 示例:

@Component
public class BeanFactoryAwareDemo implements BeanFactoryAware {

    BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public <T> T getBean(String beanName, Class<T> c){
        return beanFactory.getBean(beanName, c);
    }
}

@Component(value = "wpz")
public class Dog {

    public void sayName(){
        System.out.println("im wpz!");
    }
}

@SpringBootTest(classes = SpringDemoMain.class)
public class AwareTest {
    @Autowired
    private BeanFactoryAwareDemo bd;

    @Test
    public void test(){
        Dog dog = bd.getBean("wpz", Dog.class);
        dog.sayName();
    }
}

BeanNameAware 示例

@Component
public class BeanNameAwareDemo implements BeanNameAware {

    @Override
    public void setBeanName(String s) {
        System.out.println("这是我的名字:" + s);
    }

}

@SpringBootTest(classes = SpringDemoMain.class)
public class AwareTest {
  @Autowired
  private BeanFactoryAwareDemo beanFactoryAwareDemo;
}

8. ApplicationContextInitializer ??

9. ResourcePatternResolver

ResourcePatternResolver 资源匹配接口。在 springAnnotationConfigApplicationContext.scan() 方法,以及 mybatis 的 MybatisProperties 类发现 mapper 中都有使用。

实现类 PathMatchingResourcePatternResolver 是一个Ant模式通配符的Resource查找器,可以用来解析资源文件,主要是用来解析类路径下的资源文件。当然它也可以用来解析其它资源文件,如基于文件系统的本地资源文件。

1. 获取文件系统文件

file 就表示文件系统目录

public void test1(){
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    //获取的是项目根目录下的文件
    Resource resource = resolver.getResource("file:ReadMe.md");
    print(resource, "file:相对路径");

    //磁盘绝对路径
    Resource resource1 = resolver.getResource("file:D:\\test.js");
    print(resource1, "file:磁盘绝对路径");
}

2. 获取类路径下文件

无协议或者 classpath 表示类路径下(编译后的 classes 目录)

public void test2(){
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    //读取资源目录 resource 下文件
    Resource resource = resolver.getResource("application.properties");
    print(resource, "无前缀 resource");

    //如果不是根目录,也可以指定目录
    Resource resource1 = resolver.getResource("file/pz.txt");
    print(resource1, "无前缀带目录 resource");

    //也可以明确指定 classpath
    Resource resource2 = resolver.getResource("classpath:file/pz.txt");
    print(resource2, "classpath 带目录 resource");

    //这里是获取编译后的
    Resource resource3 = resolver.getResource("com/demo/aware/Dog.class");
    print(resource3, "class 文件");
}

3. 获取所有类路径下

classpath* 和 classpath 区别在于:classpath前缀只能获取当前类路径下的资源文件,而classpath*前缀可以获取所有类路径下的资源文件,包括jar包中的

public void test3() throws IOException {
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    //读取资源目录 resource 下文件
    Resource[] resource = resolver.getResources("classpath*:META-INF/spring.factories");
    for(Resource resource1:resource) {
        print(resource1, "classpath* resource");
    }
}

4. 通配符

* 通配路径或者文件名

/**
 * 得配合 classpath*
 * */
public void test4() throws IOException {
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

    //文件名匹配
    Resource[] resources = resolver.getResources("classpath*:file/p*.txt");
    for(Resource resource : resources) {
        print(resource, "文件名通配符");
    }

    //单个路径匹配 * 匹配一层目录
    Resource[] resources1 = resolver.getResources("classpath*:*/pz.txt");
    for(Resource resource : resources1) {
        print(resource, "单个路径通配符");
    }

    //多个路径匹配 ** 匹配多层目录
    Resource[] resources2 = resolver.getResources("classpath*:**/pz.txt");
    for(Resource resource : resources2) {
        print(resource, "多个路径通配符");
    }
}

10. BeanUtils

Spring 提供的 bean 工具类。

1. 方法

public static <T> T instantiateClass(Class<T> clazz)   通过反射返回一个实例

11. Metadata

  Metadata 表示元数据,就是数据的数据,org.springframework.core.type包名下。两个顶级接口:ClassMetadataAnnotatedTypeMetadata

1. ClassMetadata

ClassMetadata,顾名思义,就是表示 Java 中 类 的元数据

  • 类名;
  • 是否是注解;
  • 是否是接口;
  • 是否抽象类;
  • 父类;
  • 实现的接口等;

2. AnnotatedTypeMetadata

这个接口表示的是注解元素 (AnnotatedElement) 的元数据,我们常见的Class、Method、Constructor、Parameter等等都属于它的子类都属于注解元素。简单理解:只要能在上面标注注解的元素都属于这种元素。

3. AnnotationMetadata

这是理解 Spring 注解编程的必备知识,它是 ClassMetadata 和 AnnotatedTypeMetadata 的子接口,具有两者共同能力,并且新增了访问注解的相关方法。可以简单理解为它是对注解的抽象。

经常这么使用得到注解里面所有的属性值:
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annoMetadata, annType);

posted @ 2024-04-26 16:51  primaryC  阅读(71)  评论(0编辑  收藏  举报