如何在获得 Spring 的功能时做些扩展框架的使用该怎么操作?
BeanFactoryPostProcessor
、BeanFactoryPostProcessor
、InitializingBean
、DisposableBean
。BeanFactory
、ApplicationContext
、BeanClassLoader
等这些功能做一些扩展框架的使用时该怎么操作呢?
希望拿到 Spring 框架中一些提供的资源,那么首先需要考虑以一个什么方式去获取,之后定义出来的获取方式,在 Spring 该怎么去承接?
实现了这两项内容,就可以扩展出你需要的一些属于 Spring 框架本身的能力了。
BeanFactory
、ApplicationContext
时,也可以通过此类方式进行实现。
instanceof
进行判断和调用。Aware
,在 Spring 框架中它是一种感知标记性接口,具体的子类定义和实现能感知容器中的相关对象。
Aware
的接口包括:BeanFactoryAware
、BeanClassLoaderAware
、BeanNameAware
、ApplicationContextAware
。BeanFactoryAware
、BeanClassLoaderAware
、BeanNameAware
)在 factory
的 support
文件夹下。ApplicationContextAware
)是在 context
的 support
中。AbstractApplicationContext
的具体实现中会用到向 beanFactory
添加 BeanPostProcessor
内容的 ApplicationContextAwareProcessor
操作。AbstractAutowireCapableBeanFactory
创建 createBean
时处理相应的调用操作。spring-step-08
|-src
|-main
| |-java
| |-com.lino.springframework
| |-beans
| | |-factory
| | | |-config
| | | | |-AutowireCapableBeanFactory.java
| | | | |-BeanDefinition.java
| | | | |-BeanFactoryPostProcessor.java
| | | | |-BeanPostProcessor.java
| | | | |-BeanReference.java
| | | | |-ConfigurableBeanFactory.java
| | | | |-SingletonBeanRegistry.java
| | | |-support
| | | | |-AbstractAutowireCapableBeanFactory.java
| | | | |-AbstractBeabDefinitionReader.java
| | | | |-AbstractBeabFactory.java
| | | | |-BeabDefinitionReader.java
| | | | |-BeanDefinitionRegistry.java
| | | | |-CglibSubclassingInstantiationStrategy.java
| | | | |-DefaultListableBeanFactory.java
| | | | |-DefaultSingletonBeanRegistry.java
| | | | |-DisposableBeanAdapter.java
| | | | |-InstantiationStrategy.java
| | | | |-SimpleInstantiationStrategy.java
| | | |-support
| | | | |-XMLBeanDefinitionReader.java
| | | |-Aware.java
| | | |-BeanClassLoaderAware.java
| | | |-BeanFactory.java
| | | |-BeanFactoryAware.java
| | | |-BeanNameAware.java
| | | |-ConfigurableListableBeanFactory.java
| | | |-DisposableBean.java
| | | |-HierarcgicalBeanFactory.java
| | | |-InitializingBean.java
| | | |-ListableBeanFactory.java
| | |-BeansException.java
| | |-PropertyValue.java
| | |-PropertyValues.java
| |-context
| | |-support
| | | |-AbstractApplicationContext.java
| | | |-AbstractRefreshableApplicationContext.java
| | | |-AbstractXmlApplicationContext.java
| | | |-ApplicationContextAwareProcessor.java
| | | |-ClassPathXmlApplicationContext.java
| | |-ApplicationContext.java
| | |-ApplicationContextAware.java
| | |-ConfigurableApplicationContext.java
| |-core.io
| | |-ClassPathResource.java
| | |-DefaultResourceLoader.java
| | |-FileSystemResource.java
| | |-Resource.java
| | |-ResourceLoader.java
| | |-UrlResource.java
| |-util
| | |-ClassUtils.java
|-test
|-java
|-com.lino.springframework.test
|-bean
| |-UserDao.java
| |-UserService.java
|-ApiTest.java
|-resources
|-spring.xml
Aware
感知的定义和对容器感知的实现。Aware
有四个继承的接口,其他这些接口的继承都是为了继承一个标记,有了标记的存在更方便类的操作和具体判断实现。ApplicationContext
并不是在 AbstractAutowireCapableBeanFactory
中 createBean
方法下的内容。
addBeanPostProcessor
,再由 createBean
统一调用 applyBeanPostProcessorBeforeInitialization
时进行操作。Aware.java
package com.lino.springframework.beans.factory;
/**
* @description: 标记类接口,实现该接口可以被Spring容器感知
*/
public interface Aware {
}
instanceof
一起判断使用。BeanFactoryAware.java
package com.lino.springframework.beans.factory;
import com.lino.springframework.beans.BeansException;
/**
* @description: 实现此接口,即能感知到所属的 BeanFactory
*/
public interface BeanFactoryAware extends Aware {
/**
* 设置对象工厂
*
* @param beanFactory 对象工厂
* @throws BeansException 异常
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
BeanClassLoaderAware.java
package com.lino.springframework.beans.factory;
/**
* @description: 实现此接口,即能感知到所属的 ClassLoader
*/
public interface BeanClassLoaderAware extends Aware {
/**
* 设置类加载器
*
* @param classLoader 类加载器
*/
void setBeanClassLoader(ClassLoader classLoader);
}
BeanNameAware.java
package com.lino.springframework.beans.factory;
/**
* @description: 实现此接口,即能感知到所属的 BeanName
*/
public interface BeanNameAware {
/**
* 设置对象名称
*
* @param name 对象名称
*/
void setBeanName(String name);
}
ApplicationContextAware.java
package com.lino.springframework.context;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.Aware;
/**
* @description: 实现此接口,即能感知到所属的 ApplicationContext
*/
public interface ApplicationContextAware extends Aware {
/**
* 设置应用上下文
*
* @param applicationContext 应用上下文
* @throws BeansException 异常
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
ApplicationContextAwareProcessor.java
package com.lino.springframework.context.support;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.context.ApplicationContext;
import com.lino.springframework.context.ApplicationContextAware;
/**
* @description: 通过 BeanPostProcessor 实现类感知应用上下文对象
*/
public class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(applicationContext);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
ApplicationContext
的获取并不能直接在创建 Bean 时候就可以拿到,所以需要在 refresh
操作时,把 ApplicationContext
写入到一个包装的 BeanPostProcessor
中去,再由 AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization
方法调用。AbstractApplicationContext.java
package com.lino.springframework.context.support;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.ConfigurableListableBeanFactory;
import com.lino.springframework.beans.factory.config.BeanFactoryPostProcessor;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.context.ConfigurableApplicationContext;
import com.lino.springframework.core.io.DefaultResourceLoader;
import java.util.Map;
/**
* @description: 抽象应用上下文
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException {
// 1.创建 BeanFactory,并加载 BeanDefinition
refreshBeanFactory();
// 2.获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 3.添加 ApplicationContextAwareProcessor,让继承自 ApplicationContextAware 的 Bean 对象都能感知所属的 ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 4.在 Bean 实例化之前,执行 BeanFactoryPostProcess
invokeBeanFactoryPostProcessor(beanFactory);
// 5.BeanPostProcessor 需要提前与其他 Bean 对象实例化之前执行注册操作
registerBeanPostProcessor(beanFactory);
// 6.提前实例化单例 Bean 对象
beanFactory.preInstantiateSingletons();
}
...
}
refresh()
方法就是整个 Spring 容器的操作过程,这次新增加了 addBeanPostProcessor
操作。ApplicationContextAwareProcessor
,让继承自 ApplicationContextAware
的 Bean 对象都能感知所属的 ApplicationContext
。AbstractBeanFactory.java
package com.lino.springframework.beans.factory.support;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.config.BeanDefinition;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.beans.factory.config.ConfigurableBeanFactory;
import com.lino.springframework.util.ClassUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 抽象的 Bean 工厂基类,定义模板方法
*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements ConfigurableBeanFactory {
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
...
public ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
}
ClassLoader
对像,并提供一个获取对象类加载器的方法。getBeanClassLoader()
。AbstractAutowireCapableBeanFactory.java
package com.lino.springframework.beans.factory.support;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValue;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.*;
import com.lino.springframework.beans.factory.config.AutowireCapableBeanFactory;
import com.lino.springframework.beans.factory.config.BeanDefinition;
import com.lino.springframework.beans.factory.config.BeanPostProcessor;
import com.lino.springframework.beans.factory.config.BeanReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @description: 实现默认bean创建的抽象bean工厂超类
* @author: lingjian
* @createDate: 2022/11/22 14:39
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
...
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
// invokeAwareMethods
if (bean instanceof Aware) {
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(this);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
}
// 1.执行 BeanPostProcessor Before 处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 执行 Bean 对象的初始化方法
try {
invokeInitMethods(beanName, wrappedBean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
}
// 2.执行 BeanPostProcessor After 处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
...
}
initializeBean
中,通过判断 bean instanceof Aware
,调用三个接口方法。这样就能通知到已经实现了此接口的类。
((BeanFactoryAware) bean).setBeanFactory(this)
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader())
((BeanNameAware) bean).setBeanName(beanName)
BeanPostProcessor
中添加了 ApplicationContextAwareProcessor
,此时在这个方法中也会被调用到具体的类实现,得到一个 ApplicationContext
属性。UserService.java
package com.lino.springframework.test.bean;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.*;
import com.lino.springframework.context.ApplicationContext;
import com.lino.springframework.context.ApplicationContextAware;
/**
* @description: 模拟用户 Bean 对象
*/
public class UserService implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware {
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
private String uId;
private String company;
private String location;
private UserDao userDao;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("ClassLoader: " + classLoader);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setBeanName(String name) {
System.out.println("Bean Name is: " + name);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* 查询用户信息
*/
public String queryUserInfo() {
return userDao.queryUserName(uId) + "," + company + "," + location;
}
public String getuId() {
return uId;
}
public void setuId(String uId) {
this.uId = uId;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}
BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware
四个感知的实现类,并在类中的实现相应的接口方法。ApiTest.java
@Test
public void test_xml() {
// 1.初始化 BeanFactory
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
// 2.获取Bean对象调用方法
UserService userService = applicationContext.getBean("userService", UserService.class);
String result = userService.queryUserInfo();
System.out.println("测试结果:" + result);
System.out.println("ApplicationContextAware: " + userService.getApplicationContext());
System.out.println("BeanFactoryAware: " + userService.getBeanFactory());
}
测试结果
执行:init-method
ClassLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
Bean Name is: userService
测试结果:张三,阿里,杭州
ApplicationContextAware: com.lino.springframework.context.support.ClassPathXmlApplicationContext@56cbfb61
BeanFactoryAware: com.lino.springframework.beans.factory.support.DefaultListableBeanFactory@1134affc
执行:destroy-method
BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware
),已经可以正常输出结果。