上一章中是在Bean注册后实行属性的填充,和初始化过程中的前置处理和后置处理.今天撸的这块代码,缺胳膊少腿的, 所以我决定一边跟着撸 一边解决问题,把那些缺的胳膊和腿补上!
两种形式可以实现这一章的需求, 一是通过实现Spring的默认类,重写方法,然后spring在执行时调用.
另一种则是写在配置文件中的属性,通过init-method和destroy-method来手动注册
定义初始化和销毁方法的接口
InitializingBean
初始化方法,言简意赅的方法名,在初始化后执行
package com.linnine.spring.beans.factory;
public interface InitializingBean {
/**
* 在属性填充后调用
* @throws Exception
*/
void afterPropertiesSet() throws Exception;
}
DisposableBean
public interface DisposableBean {
/**
* 销毁方法
* @throws BeansException
*/
void destroy() throws Exception;
}
在spring中比较常用的存在,在需要结合spring实现的组件中很常见,经常用来进行一些参数的初始化和销毁操作,比如接口暴露/数据库数据读取/配置文件加载等待.
Bean定义新增初始化和销毁方法
package com.linnine.spring.beans.factory.config;
import com.linnine.spring.beans.PropertyValues;
import lombok.Data;
@Data
public class BeanDefinition {
private Class beanClass;
//补充属性
private PropertyValues propertyValues;
//初始化
private String initMethodName;
//销毁
private String destroyMethodName;
//这里升级为只传类型,而不是实例 在需要的时候才去实例化
public BeanDefinition(Class beanClass){
this.beanClass=beanClass;
//如果没有就传个空的 避免后去捞的时候空指针异常
this.propertyValues=new PropertyValues();
}
public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
this.beanClass = beanClass;
this.propertyValues = propertyValues;
}
}
执行Bean对象的初始化方法
AbstractAutowireCapableBeanFactory
package com.linnine.spring.beans.factory.support;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.linnine.spring.beans.BeansException;
import com.linnine.spring.beans.PropertyValue;
import com.linnine.spring.beans.PropertyValues;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.InitializingBean;
import com.linnine.spring.beans.factory.config.AutowireCapableBeanFactory;
import com.linnine.spring.beans.factory.config.BeanDefinition;
import com.linnine.spring.beans.factory.config.BeanPostProcessor;
import com.linnine.spring.beans.factory.config.BeanReference;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@Getter
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy =new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition,Object[] args) throws BeansException {
Object bean;
bean = createBeanInstance(beanDefinition,args);
//补充属性
applyPropertyValues(bean,beanDefinition);
//执行bean的初始化方法和BeanPostProcessor的前置方法和后置方法
bean = initializeBean(beanName,bean,beanDefinition);
//注册 有实现 DisposableBean 接口的bean对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingletonBean(beanName,bean);
return bean;
}
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition){
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition){
//执行前置处理器
Object wrappedBean=applyBeanPostProcessorsBeforeInitialization(bean,beanName);
//待完成 执行初始化方法
try {
invokeInitMethods(beanName, wrappedBean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
}
//执行后处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
return wrappedBean;
}
/**
* 08 完善初始化方法
* @param beanName
* @param bean
* @param beanDefinition
* @throws Exception
*/
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
//执行初始化
if (bean instanceof InitializingBean){
((InitializingBean) bean).afterPropertiesSet();
}
//获取初始化方法名称
String initMethodName = beanDefinition.getInitMethodName();
if (StringUtils.isNotEmpty(initMethodName)){
//去类里面获取方法
Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
if (null == initMethod){
throw new BeansException("Could not find an init initMethod named '" + initMethodName + "' on bean with name '" + beanName + "'");
}
//执行初始化方法
initMethod.invoke(bean);
}
}
private Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
Object result =existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null != current) {
result =current;
}
}
return result;
}
protected Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName){
Object result =existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null != current) {
result =current;
}
}
return result;
}
protected Object createBeanInstance( BeanDefinition beanDefinition,Object... args){
Constructor constructor =null;
Class beanClass = beanDefinition.getBeanClass();
//获取所有的构造方法
Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();
//简单对比 spring还会对比类型
for (Constructor ctor : declaredConstructors) {
if (null!=args && ctor.getParameterTypes().length ==args.length){
constructor=ctor;
break;
}
}
//创建
return getInstantiationStrategy().instantiate(beanDefinition,constructor,args);
}
//手撸05新增
protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition){
//取出填入的属性
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
//如果是个实例对象
if (value instanceof BeanReference){
BeanReference beanReference=(BeanReference)value;
//通过bean名去获取bean 跳过循环依赖 后面再补充
value = getBean(beanReference.getBeanName());
}
//通过名称注入属性
BeanUtil.setFieldValue(bean,name,value);
}
}
}
在Bean创建时 注册 销毁方法对象
这里只是注册进去,在需要时调用
package com.linnine.spring.beans.factory.support;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.linnine.spring.beans.BeansException;
import com.linnine.spring.beans.PropertyValue;
import com.linnine.spring.beans.PropertyValues;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.InitializingBean;
import com.linnine.spring.beans.factory.config.AutowireCapableBeanFactory;
import com.linnine.spring.beans.factory.config.BeanDefinition;
import com.linnine.spring.beans.factory.config.BeanPostProcessor;
import com.linnine.spring.beans.factory.config.BeanReference;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@Getter
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
private InstantiationStrategy instantiationStrategy =new CglibSubclassingInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition,Object[] args) throws BeansException {
Object bean;
bean = createBeanInstance(beanDefinition,args);
//补充属性
applyPropertyValues(bean,beanDefinition);
//执行bean的初始化方法和BeanPostProcessor的前置方法和后置方法
bean = initializeBean(beanName,bean,beanDefinition);
//注册 有实现 DisposableBean 接口的bean对象
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
addSingletonBean(beanName,bean);
return bean;
}
/**
* 08新增 注册销毁方法类
* @param beanName
* @param bean
* @param beanDefinition
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition){
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition){
//执行前置处理器
Object wrappedBean=applyBeanPostProcessorsBeforeInitialization(bean,beanName);
//待完成 执行初始化方法
try {
invokeInitMethods(beanName, wrappedBean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
}
//执行后处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
return wrappedBean;
}
/**
* 08 完善初始化方法
* @param beanName
* @param bean
* @param beanDefinition
* @throws Exception
*/
private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
//执行初始化
if (bean instanceof InitializingBean){
((InitializingBean) bean).afterPropertiesSet();
}
//获取初始化方法名称
String initMethodName = beanDefinition.getInitMethodName();
if (StringUtils.isNotEmpty(initMethodName)){
//去类里面获取方法
Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
if (null == initMethod){
throw new BeansException("Could not find an init initMethod named '" + initMethodName + "' on bean with name '" + beanName + "'");
}
//执行初始化方法
initMethod.invoke(bean);
}
}
private Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
Object result =existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (null != current) {
result =current;
}
}
return result;
}
protected Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName){
Object result =existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (null != current) {
result =current;
}
}
return result;
}
protected Object createBeanInstance( BeanDefinition beanDefinition,Object... args){
Constructor constructor =null;
Class beanClass = beanDefinition.getBeanClass();
//获取所有的构造方法
Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();
//简单对比 spring还会对比类型
for (Constructor ctor : declaredConstructors) {
if (null!=args && ctor.getParameterTypes().length ==args.length){
constructor=ctor;
break;
}
}
//创建
return getInstantiationStrategy().instantiate(beanDefinition,constructor,args);
}
//手撸05新增
protected void applyPropertyValues(Object bean, BeanDefinition beanDefinition){
//取出填入的属性
PropertyValues propertyValues = beanDefinition.getPropertyValues();
for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
//如果是个实例对象
if (value instanceof BeanReference){
BeanReference beanReference=(BeanReference)value;
//通过bean名去获取bean 跳过循环依赖 后面再补充
value = getBean(beanReference.getBeanName());
}
//通过名称注入属性
BeanUtil.setFieldValue(bean,name,value);
}
}
}
钩子函数调用销毁方法
package com.linnine.spring.context;
import com.linnine.spring.beans.BeansException;
public interface ConfigurableApplicationContext extends ApplicationContext{
/**
* 刷新容器
* @throws BeansException
*/
void refresh() throws BeansException;
/**
* 钩子
*/
void registerShutdownHook();
/**
* 关闭
*/
void close() throws Exception;
}
AbstractApplicationContext
实现钩子
package com.linnine.spring.context.support;
import com.linnine.spring.beans.BeansException;
import com.linnine.spring.beans.factory.ConfigurableListableBeanFactory;
import com.linnine.spring.beans.factory.config.BeanFactoryPostProcessor;
import com.linnine.spring.beans.factory.config.BeanPostProcessor;
import com.linnine.spring.context.ConfigurableApplicationContext;
import com.linnine.spring.core.io.DefaultResourceLoader;
import java.util.Map;
/**
* 应用上下文 抽象类实现
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException {
//创建beanFactory, 并加载BeanDefinition
refreshBeanFactory();
//获取BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//在Bean实例化前 调用后处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册bean处理器
registerBeanPostProcessors(beanFactory);
//提前实例化单例对象
beanFactory.preInstantiateSingletons();
}
private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//获取所有工厂后处理器
Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);
//遍历去处理
for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {
beanFactoryPostProcessor.postProcessorBeanFactory(beanFactory);
}
}
private void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
Map<String, BeanPostProcessor> beanPostProcessorMap = beanFactory.getBeansOfType(BeanPostProcessor.class);
for (BeanPostProcessor beanPostProcessor : beanPostProcessorMap.values()) {
beanFactory.addBeanPostProcessor(beanPostProcessor);
}
}
protected abstract ConfigurableListableBeanFactory getBeanFactory();
protected abstract void refreshBeanFactory();
@Override
public void registerShutdownHook(){
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
/**
* 关闭
*/
@Override
public void close(){
getBeanFactory().destroySingletons();
}
}
然后这里就上面这个方法,自己补了一下!
getBeanFactory().destroySingletons();
在ConfigurableListableBeanFactory加个接口就不贴代码了
直接贴实现类里的代码
package com.linnine.spring.beans.factory.support;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.config.SingletonBeanRegistry;
import java.util.HashMap;
import java.util.Map;
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private final Map<String, Object> singletonObjects = new HashMap<>();
private final Map<String, DisposableBean> disposableBeans = new HashMap<>();
/**
* 实现获取单例的方法
*
* @param beanName
* @return
*/
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
/**
* 提供一个包保护的方法 可以被继承此类的其他类调用
*
* @param beanName
* @param singletonObject
*/
protected void addSingletonBean(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
protected void registerDisposableBean(String beanName, DisposableBeanAdapter disposableBeanAdapter) {
disposableBeans.put(beanName,disposableBeanAdapter);
}
public void destroySingletons() {
for (DisposableBean value : disposableBeans.values()) {
try {
value.destroy();
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}
然后是测试用的业务类
UserDao使用配置文件加载初始方法和清除方法, 取代了原本的static静态代码块
package com.linnine.spring.bean.dao;
import java.util.HashMap;
import java.util.Map;
public class UserDao {
private static Map<String, String> hashMap = new HashMap<>();
/**
* 取代静态代码块,让spring来实现更优雅
*/
public void initDataMethod(){
System.out.println("执行:init-method");
hashMap.put("10001", "小傅哥");
hashMap.put("10002", "八杯水");
hashMap.put("10003", "阿毛");
}
/**
* spring 代为清除数据
*/
public void destroyDataMethod(){
System.out.println("执行:destroy-method");
hashMap.clear();
}
public String queryUserName(String uId) {
return hashMap.get(uId);
}
}
配置文件 主要改了userDao的配置
<bean id="userDao" class="com.linnine.spring.bean.dao.UserDao" init-method="initDataMethod" destroy-method="destroyDataMethod"/>
另外一种则是直接实现上面的两个接口
package com.linnine.spring.bean.service;
import com.linnine.spring.bean.dao.UserDao;
import com.linnine.spring.beans.factory.DisposableBean;
import com.linnine.spring.beans.factory.InitializingBean;
import lombok.Data;
@Data
public class UserService implements InitializingBean, DisposableBean {
private String uId;
private String company;
private String location;
private UserDao userDao;
public String queryUserInfo(){
return userDao.queryUserName(uId)+uId+company+location;
}
@Override
public void afterPropertiesSet() {
System.out.println("执行:UserService.afterPropertiesSet");
}
@Override
public void destroy() {
System.out.println("执行:UserService.destroy");
}
}
开始测试
@Test
public void test_XML(){
//初始化
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
applicationContext.registerShutdownHook();
UserService userService = (UserService) applicationContext.getBean("userService", UserService.class);
String s = userService.queryUserInfo();
System.out.println("测试结果"+s);
}
目标结果
执行:init-method
执行:UserService.afterPropertiesSet
测试结果:小傅哥,腾讯,深圳
执行:UserService.destroy
执行:destroy-method
我的结果1:
执行:UserService.afterPropertiesSet
测试结果null10001腾讯深圳
执行:UserService.destroy
userDao的都没执行, 应该是没加载配置,去读取配置文件的类里面补充一下,这里只放 修改了的那一段代码
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
...
private void doLoadBeanDefinitions(InputStream inputStream) throws ClassNotFoundException {
Document doc = XmlUtil.readXML(inputStream);
Element root = doc.getDocumentElement();
NodeList childNodes = root.getChildNodes();
for (int i = 0; i < childNodes.getLength();i++) {
//判断元素
if (!(childNodes.item(i) instanceof Element)) continue;
//判断对象
if (!"bean".equals(childNodes.item(i).getNodeName())) continue;
//解析标签
Element bean = (Element) childNodes.item(i);
String id = bean.getAttribute("id");
String name = bean.getAttribute("name");
String className = bean.getAttribute("class");
//08 读取初始化方法 和销毁方法
String initMethodName = bean.getAttribute("init-method");
String destroyMethodName = bean.getAttribute("destroy-method");
//获取Class 方便获取类名
Class<?> clazz = Class.forName(className);
//优先级 id>name
String beanName = StrUtil.isNotEmpty(id)?id:name;
//如果取不到 就从类里面取
if (StrUtil.isEmpty(beanName)){
beanName = StrUtil.lowerFirst(clazz.getSimpleName());
}
//开始定义Bean
BeanDefinition beanDefinition = new BeanDefinition(clazz);
//08 加入到定义中
beanDefinition.setInitMethodName(initMethodName);
beanDefinition.setDestroyMethodName(destroyMethodName);
//读取属性并填充
NodeList beanNodeList = bean.getChildNodes();
for (int j = 0; j <beanNodeList.getLength(); j++) {
if (!(beanNodeList.item(j) instanceof Element)) continue;
//判断标签是否为属性
if (!"property".equals(beanNodeList.item(j).getNodeName())) continue;
Element property = (Element) beanNodeList.item(j);
String attrName = property.getAttribute("name");
String attrValue = property.getAttribute("value");
String attrRef = property.getAttribute("ref");
//获取属性值
Object value=StrUtil.isNotEmpty(attrRef)?(BeanReference)()->attrRef:attrValue;
PropertyValue propertyValue =new PropertyValue(attrName,value);
beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
}
if (getRegistry().containsBeanDefinition(beanName)){
throw new BeansException("Duplicate beanName[" + beanName + "] is not allowed");
}
// 注册 BeanDefinition
getRegistry().registerBeanDefinition(beanName, beanDefinition);
}
}
...
}
执行结果02:
执行:init-method
执行:UserService.afterPropertiesSet
测试结果小傅哥10001腾讯深圳
执行:UserService.destroy
奇怪 没有执行userDao的销毁方法
问题找到了,判断的地方判断错了
DisposableBeanAdapter
@Override
public void destroy() throws Exception{
if (bean instanceof DisposableBean){
((DisposableBean)bean).destroy();
}else {
// 2. 配置信息 destroy-method {判断是为了避免二次执行销毁}
if (StringUtils.isNotEmpty(destroyMethodName)&& !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))){
Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
destroyMethod.invoke(bean);
}
}
}
执行:init-method
执行:UserService.afterPropertiesSet
测试结果:小傅哥10001腾讯深圳
销毁方法destroyDataMethod
执行:destroy-method
执行:UserService.destroy