Spring 扩展接口

1. 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方法

2. 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 方法在构造函数方法之后执行。

3. InitializingBean和DisposableBean

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

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

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

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

这里借用网上的一张Bean生命周期的过程图片:
在这里插入图片描述

4. 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;
    }
}

5. 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);
  	}
}

6. 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;
}

7. EnvironmentAware

实现了EnvironmentAware接口重写setEnvironment方法后,可通过 Environment 对象获取运行环境中变量。

public interface EnvironmentAware extends Aware {
	void setEnvironment(Environment environment);
}

8. EnvironmentPostProcessor

动态的读取文件,通过该接口可以加载自定义配置文件。

@FunctionalInterface
public interface EnvironmentPostProcessor {
    void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application);
}

加载自定义配置文件

public class LizqEnvironmentPostProcessor implements EnvironmentPostProcessor {
    private final Properties properties = new Properties();
    private String propertiesFile = "lizq.properties";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        Resource resource = new ClassPathResource(propertiesFile);
        environment.getPropertySources().addLast(loadProperties(resource));
    }

    private PropertySource<?> loadProperties(Resource resource) {
        if (!resource.exists()) {
            throw new RuntimeException("file not exist");
        }
        try {
            //custom.properties
            properties.load(resource.getInputStream());
            return new PropertiesPropertySource(resource.getFilename(), properties);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

9. BeanClassLoaderAware

获取Bean的类装载器。

public interface BeanClassLoaderAware extends Aware {
    void setBeanClassLoader(ClassLoader classLoader);
}

10. BeanFactoryAware

获取bean工厂。

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

11. BeanNameAware

取到了该Bean在Spring容器中的名字。

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

12. SmartLifeCycle

在Spring IOC容器创建之后、关闭之前执行自定义的操作。

public interface Lifecycle {
    void start();   // 容器启动后调用
 
    void stop();    // 容器关闭前调用
 
    boolean isRunning();  // 当前应用是否正在运行
}

13. ApplicationContextInitializer

用于在 Spring 容器刷新之前初始化 Spring ConfigurableApplicationContext 的回调接口。(剪短说就是在容器刷新之前调用该类的 initialize() 方法。并将 ConfigurableApplicationContext 类的实例传递给该方法)
通常用于需要对应用程序上下文进行编程初始化的web应用程序中。例如,根据上下文环境注册属性源或激活配置文件等。

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

	/**
	 * Initialize the given application context.
	 * @param applicationContext the application to configure
	 */
	void initialize(C applicationContext);
}

14. InstantiationAwareBeanPostProcessor

在类被加载后,实例化前,Spring 提供了一个扩展点,允许用户来控制是否在某个或某些 Bean 实例化前做一些启动动作。

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    	// 在目标bean实例化之前应用这个BeanPostProcessor
    	// 返回的bean对象可能是要使用的代理而不是目标bean,从而有效地抑制目标bean的默认实例化。
		return null;
	}

	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    	// 在bean通过构造函数或工厂方法实例化之后,但在Spring属性填充(来自显式属性或自动装配)发生之前执行操作。
    	// 这是在Spring自动装配开始之前对给定bean实例执行自定义字段注入的理想回调。
    	// 默认实现返回{@code true}。返回{@code false}还将阻止在此bean实例上调用任何后续的InstantiationAwareBeanPostProcessor实例
		return true;
	}

	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
		// 在工厂将给定的属性值应用到给定的bean之前,对它们进行ost处理。
		// 允许检查是否满足所有依赖项,例如基于bean属性设置器上的“Required”注释。
		// 还允许替换要应用的属性值,通常是通过基于原始PropertyValues创建新的MutablePropertyValues实例,添加或删除特定的值。
		return pvs;
	}

}

例如:Spring AOP 就行通过当前方式进行处理的,AbstractAutoProxyCreator 用于 AOP 代理包装每个符合条件的bean,在调用bean本身之前将其委托给指定的拦截器。
在这里插入图片描述

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
		
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			// 获取当前类匹配的具体拦截器,匹配多个pointCut
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			// 创建代理对象
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}
}

15. 后续再进行添加补充

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值