平度网站整站优化外包公司,爱站在线关键词挖掘,cent7安装wordpress,电影网站开发开题报告文章目录 一、背景二、AutowireCapableBeanFactory 方法 autowireBean 分析三、Spring 容器中 scope 为 prototype 类型 Bean 的回收机制四、总结 一、背景
最近做 DDD 实践时#xff0c;遇到业务对象需要交给 Spring 管理才能做一些职责内事情。假设账号注册邮箱应用层代码流… 文章目录 一、背景二、AutowireCapableBeanFactory 方法 autowireBean 分析三、Spring 容器中 scope 为 prototype 类型 Bean 的回收机制四、总结 一、背景
最近做 DDD 实践时遇到业务对象需要交给 Spring 管理才能做一些职责内事情。假设账号注册邮箱应用层代码流程
public void registerEmail(Long id) {Account account accountRepository.findById(id);account.registerEmail();
}其中业务对象 Account 表示账号聚合
Component
Scope(value BeanDefinition.SCOPE_PROTOTYPE)
public class Account {Autowireprivate EmailService emailService;private String id;private String name;// 其他账号属性// 注册邮箱public void registerEmail() {//....emailService.register();}
}负责 Account 的仓储服务 AccountRepository
Repository
public class AccountRepository {Autowireprivate AutowireCapableBeanFactory beanFactory;public Account findById(Long id) {// 1. 从 DB 查询AccountDO accountDO accountMapper.findById(id);// 2. 转换成业务对象Account account convert(accountDO);// 3. 交给 Spring 管理beanFactory.autowireBean(account);return account;}
}有个疑问账号每次注册邮箱后Account 实例对象即然交给 Spring 来管理那么会不会常驻在内存而引发内存溢出呢
二、AutowireCapableBeanFactory 方法 autowireBean 分析 直接看方法签名 Populate the given bean instance through applying after-instantiation callbacks and bean property post-processing (e.g. for annotation-driven injection). 翻译通过实例化后回调和 bean 属性后处理来填充指定 bean 实例 Note: This is essentially intended for (re-)populating annotated fields and methods, either for new instances or for deserialized instances. It does not imply traditional by-name or by-type autowiring of properties;翻译无论是新实例还是反序列化实例本质上是为了重新填充带注解的字段和方法。 它并不意味着传统的按名称或按类型自动装配属性。 从翻译字面意思上该方法作用只是对指定对象进行属性填充尤其是使用注解标注的属性。 再深入到源码 可以看出只做了三件事情创建 Spring 标准 Bean 对象并创建 BeanWrapper最后进行 Bean 属性填充其中 populateBean 方法并不陌生Spring Bean 进行属性填充的标准方法。上述源码中创建 existingBean 的 BeanDefinition 时同时设置了属性为原型BeanDefinition.SCOPE_PROTOTYPE也即意味着 Spring 对 existingBean 的管理同原型 Bean 的方式一样从这里也可以看出 Account 类标记的 Component 和 Scope 注解可以去除笔者已验证。
三、Spring 容器中 scope 为 prototype 类型 Bean 的回收机制
想要弄明白 Spring Bean 会不会被 JVM 正常回收要看是否会被 Spring 容器持有所以要从 Bean 创建流程入手。直接看org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean 方法源码比较简单不做深入分析直接说结论可知如果 Bean 实例是 singleton 的会从 DefaultSingletonBeanRegistry 的 singletonObjects 属性中获取如果获取不到就会创建 Bean 实例存放到 singletonObjects 属性中
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {/** Logger available to subclasses */protected final Log logger LogFactory.getLog(getClass());/** Cache of singleton objects: bean name -- bean instance */private final MapString, Object singletonObjects new ConcurrentHashMap(256);//......}DefaultListableBeanFactory 是 Spring IOC 容器的实现归 Spring 容器管理自然单例 Bean 也归 Spring 容器管理所以说正常作用域为 singleton 的 Bean其生命周期会长期被 Spring 容器管理直到 Spring 容器被销毁。而作用域为 prototype 的 Bean 和正常 Java 对象一样 new 出来使用完就会被 JVM 回收。 四、总结
通过 AutowireCapableBeanFactory 方法 autowireBean 可以将对象装配成 Spring 管理的标准 Bean 对象主要是用于来填充有注解的属性这样才可以使用 Spring 的 DI 特性。通过代码 new 出来的对象使用 AutowireCapableBeanFactory 方法 autowireBean 填充属性成为标准 Spring Bean 后不用担心内存溢出的问题本质上和 Spring prototype Bean 的回收机制一样使用完就有可能被 JVM 回收掉。