Spring扩展接口知识总结

一、BeanPostProcessor

BeanPostProcessor 接口是 Spring 提供的众多接口之一,他的作用主要是如果需要在Spring 容器完成 Bean 的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,可以通过实现 BeanPostProcessor 来完成。

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    	// bean初始化方法调用前被调用
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    	// bean初始化方法调用后被调用
        return bean;
    }
}

运行顺序:

----------------Spring IOC容器实例化Bean
----------------调用BeanPostProcessor的postProcessBeforeInitialization方法
----------------调用bean实例的初始化方法
----------------调用BeanPostProcessor的postProcessAfterInitialization方法

二、BeanFactoryPostProcessor

BeanFactoryPostProcessor 接口与 BeanPostProcessor 接口类似,可以对bean的定义(配置元数据)进行处理;也就是spring ioc运行BeanFactoryPostProcessor 在容器实例化任何其他的bean之前读取配置元数据,并有可能修改它;
如果业务需要,可以配置多个BeanFactoryPostProcessor 的实现类,通过 ”order” 控制执行次序(要实现 Ordered 接口)。

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        System.out.println("----------------execute MyBeanFactoryPostProcessor constructor");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("----------------execute MyBeanFactoryPostProcessor postProcessBeanFactory");
    }
}

打印输出:

----------------execute MyBeanFactoryPostProcessor constructor
----------------execute MyBeanFactoryPostProcessor postProcessBeanFactory

postProcessBeanFactory 方法在构造函数方法之后执行。

三、InitialingBean和DisposableBean

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

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

DisposableBean 也是一个接口,提供了一个唯一的方法destory(),凡是继承该接口的类,在Bean生命周期结束前都会执行该方法。

public interface DisposableBean {
    void destroy() throws Exception;
}

这里借用网上的一张Bean生命周期的过程图片:

四、FactoryBean

FactoryBean 是一个接口,当在 IOC 容器中的 Bean 实现了 FactoryBean 后,通过 getBean(String BeanName) 获取到的Bean对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象。

public interface FactoryBean<T> {
	// 获取类对象
    @Nullable
    T getObject() throws Exception;
    // 获取类类型
    @Nullable
    Class<?> getObjectType();
	// 是否单例
    default boolean isSingleton() {
        return true;
    }
}

五、BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 可以完成新的 BeanDefinition 注册,对已有 BeanDefinition 进行修改等操作。

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * 在Spring的标准初始化完成之后,此时所有的符合 Spring 规则的BeanDefinition已经全部完成加载,但是还没有任何一个 Bean 被初始化,
	 * Spring允许在下一个post-processing开始处理之前通过此接口添加更多的BeanDefinition
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

写一个类实现 BeanDefinitionRegistryPostProcessor 往容器中手动注册一个BeanDefinition。

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 创建一个bean的定义类的对象
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(MyMapperFactoryBean.class);
        // 将Bean 的定义注册到Spring环境
        beanDefinitionRegistry.registerBeanDefinition("myMapperFactoryBean", rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// bean的名字为key, bean的实例为value
    }
}

MyMapperFactoryBean :

public class MyMapperFactoryBean implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        // 创建一个代理对象
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{TestBeanDefRegPostProMapper.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("----------execute:" + method.getName());
                        Class<?> returnType = method.getReturnType();
                        return "xxxxxxxxxxxx";
                    }
                });
    }

    @Override
    public Class<?> getObjectType() {
        return TestBeanDefRegPostProMapper.class;
    }
}

TestBeanDefRegPostProMapper 接口:

public interface TestBeanDefRegPostProMapper {
    String exexute();
}

测试:

@SpringBootApplication
public class SpringbootApplication implements CommandLineRunner {

    @Autowired
    private TestBeanDefRegPostProMapper testBeanDefRegPostProMapper;

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
		System.out.println(testBeanDefRegPostProMapper.exexute());
    }
}

测试结果:

----------execute:exexute
xxxxxxxxxxxx

最经典的案例就是Mybatis与Spring集成中的 MapperScannerConfigurer 和 MapperFactoryBean

MapperScannerConfigurer :

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
	@Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    if (this.processPropertyPlaceHolders) {
      processPropertyPlaceHolders();
    }

    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    scanner.setAnnotationClass(this.annotationClass);
    scanner.setMarkerInterface(this.markerInterface);
    scanner.setSqlSessionFactory(this.sqlSessionFactory);
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    scanner.registerFilters();
    // 扫描Mybatis配置MapperScan包,进行注册,将每一个Mapper接口都注册为一个MapperFactoryBean对象
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
  }
}

MapperFactoryBean:

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
	@Override
  	public T getObject() throws Exception {
  		// 返回一个代理对象,用于执行sql
    	return getSqlSession().getMapper(this.mapperInterface);
  	}
}

六、BeanNameAware、ApplicationContextAware 和 BeanFactoryAware

1、实现 BeanNameAware 接口的 Bean,在 Bean 加载的过程中可以获取到该 Bean 的 id。

public interface BeanNameAware extends Aware {
    void setBeanName(String beanName);
}

2、实现 ApplicationContextAware 接口的 Bean,在 Bean 加载的过程中可以获取到 Spring的ApplicationContext,ApplicationContext 是 Spring 应用上下文,从 ApplicationContext 中可以获取包括任意的 Bean 在内的大量 Spring 容器内容和信息。

public interface ApplicationContextAware extends Aware {
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

3、实现 BeanFactoryAware 接口的 Bean,在 Bean 加载的过程中可以获取到加载该 Bean的BeanFactory。

public interface BeanFactoryAware extends Aware {
    void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}

到此这篇关于Spring扩展接口知识总结的文章就介绍到这了,更多相关Spring扩展接口内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot集成Spring security JWT实现接口权限认证

    1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjw

  • SpringBoot 防止接口恶意多次请求的操作

    前言 刚写代码不就,还不能做深层次安全措施,今天研究了一下基本的防止接口多次恶意请求的方法. 思路 1:设置同一IP,一个时间段内允许访问的最大次数 2:记录所有IP单位时间内访问的次数 3:将所有被限制IP存到存储器 4:通过IP过滤访问请求 该demo只有后台Java代码,没有前端 代码 首先是获取IP的工具类 public class Ipsettings { public static String getRemoteHost(HttpServletRequest request) {

  • SpringBoot使用Feign调用其他服务接口

    使用SpringCloud的Feign组件能够为服务间的调用节省编码时间并提高开发效率,当服务本身不复杂时可以单独将该组件拿出使用. 引入依赖 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign --> <dependency> <groupId>org.springframework.cloud</groupId>

  • Spring Boot接口限流的常用算法及特点

    前言 在一个高并发系统中对流量的把控是非常重要的,当巨大的流量直接请求到我们的服务器上没多久就可能造成接口不可用,不处理的话甚至会造成整个应用不可用. 那么何为限流呢?顾名思义,限流就是限制流量,就像你宽带包了1个G的流量,用完了就没了.通过限流,我们可以很好地控制系统的qps,从而达到保护系统的目的.本篇文章将会介绍一下常用的限流算法以及他们各自的特点. 算法介绍 计数器法 计数器法是限流算法里最简单也是最容易实现的一种算法.比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个.

  • Springboot添加支付接口

    1. 支付宝支付接口(沙箱实现) 1.1 支付宝沙箱账号获取 官网 此处作者已经申请了一个沙箱账号,申请过程就不再赘述 如下图: 此处可以自行设置账户金额 1.2 下载客户端(目前好像只支持Android) 下载完成后根据官方提供的账号以及密码登录手机端支付宝账号 如图(商家账号): 1.3 代码配置 工具类AlipayConfig public class AlipayConfig { //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 应用ID,您的APPI

  • SpringBoot项目如何把接口参数中的空白值替换为null值(推荐)

    问题发生 我们公司代码生成的时候,查询列表统一都是使用了setEntity() ,查询写法如下: public List<BasReservoirArea> selectList(BasReservoirArea basReservoirArea) { QueryWrapper<BasReservoirArea> where = new QueryWrapper<>(); where.setEntity(basReservoirArea); return baseMap

  • Spring的BeanFactoryPostProcessor接口示例代码详解

    接口简介 BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它. BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在

  • 使用SpringBoot跨系统调用接口的方案

    一.简介 项目开发中存在系统之间互调问题,又不想用dubbo,这里提供几种springboot方案: 1.使用Feign进行消费(推荐) 2.使用原始httpClient请求 3.使用RestTemplate方法 二.方案 方案一:使用Feign进行消费(推荐) 1.在maven中添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-st

  • Springboot 扫描mapper接口的2种操作

    方式一: 在所有mapper接口使用@Mapper注解 @Mapper (将包中的所有接口都标注为DAO层接口) public interface UserMapper { UserInfo getUserInfo(@Param("userId") String userId); } 方式二: 在springboot的启动类使用@MapperScan注解 (作用:将指定包中的所有接口都标注为DAO层接口,相当于在每一个接口上写@Mapper) @SpringBootApplicatio

  • 详解常用的Spring Bean扩展接口

    前言 Spring是一款非常强大的框架,可以说是几乎所有的企业级Java项目使用了Spring,而Bean又是Spring框架的核心. Spring框架运用了非常多的设计模式,从整体上看,它的设计严格遵循了OCP----开闭原则,即: 1.保证对修改关闭,即外部无法修改Spring整个运作的流程 2.提供对扩展开放,即可以通过继承.实现Spring提供的众多抽象类与接口来改变类加载的行为 开卷有益,阅读Spring源码(无需每个类都看得很细,大体流程能梳理出来即可)对于个人水平的提升是帮助非常大

随机推荐