Bean的Aware接口&bean作用域,增加prototype的支持&FactoryBean
代码地址:WangChao-ly/chao-spring at aware-interface (github.com)
建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!
- Bean的Aware接口 Aware接口总的来说是可以让用户得到自己所属的BeanFactory和Application
- Aware接口
/**
* 标记类接口,实现该接口能感知容器类接口
* @author WangChao
* @version 1.0
* @date 2023/6/28 9:48
*/
public interface Aware {
}
- BeanFactoryAware:该接口是用来获取Bean对应的BeanFactory,用来标识注入的bean是不是需要获取它的BeanFactory。
public interface BeanFactoryAware extends Aware{
/**
* 设置所属BeanFactory
* @param beanFactory
*/
void setBeanFactory(BeanFactory beanFactory);
}
- initializeBean方法中,判断bean是不是BeanFactoryAware类型,如果是,则将当前的BeanFactory注入进去。
protected Object initializeBean(String beanName,Object bean,BeanDefinition beanDefinition){
//设置BeanFactory
if(bean instanceof BeanFactoryAware){
((BeanFactoryAware) bean).setBeanFactory(this);
}
//执行BeanPostProcessor的前置处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean,beanName);
try{
invokeInitMethods(beanName,wrappedBean,beanDefinition);
}catch (Throwable ex) {
throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", ex);
}
//执行BeanPostProcessor的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(bean,beanName);
return wrappedBean;
}
- ApplicationContext同理,不同的是,它是用的一个BeanPostProcessor切面,切面中检测到是否为继承了ApplicationContextAware类,如果是,则在bean中设置其ApplicationContext信息。
- 测试代码
- bean作用域,增加prototype的支持
- 在BeanDefinition中扩展几个属性,包括scope和是否单例等
private String scope = SCOPE_SINGLETON;
/**
* 提供判断方法
*/
private boolean singleton = true;
private boolean prototype = false;
/**
* 设置是否单例
* @param scope
*/
public void setScope(String scope){
this.scope = scope;
this.singleton = SCOPE_SINGLETON.equals(scope);
this.prototype = SCOPE_PROTOTYPE.equals(scope);
}
public boolean isSingleton(){
return this.singleton;
}
public boolean isPrototype(){
return this.prototype;
}
- 在xml读取时候,读取对应的scope信息,看用户设置是不是单例,从而设置对应的BeanDefinitin信息
//设置是否单例
if(StrUtil.isNotEmpty(beanScope)){
beanDefinition.setScope(beanScope);
}
- 在创建Bean时,如果不是单例,不需要将bean加入容器中,同时也不需要注册有销毁功能的bean
//注册有销毁方法的bean
registerDisposableBeanIfNecessary(beanName,bean,beanDefinition);
//不是单例不需要加入容器中
if(beanDefinition.isSingleton()){
addSingleton(beanName,bean);
}
/**
* 注册有销毁方法的bean,即bean继承自DisposableBean或有自定义的销毁方法
* @param beanName
* @param bean
* @param beanDefinition
*/
protected void registerDisposableBeanIfNecessary(String beanName,Object bean,BeanDefinition beanDefinition){
//只有singleton类型bean会执行销毁方法
if(beanDefinition.isSingleton()){
if(bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())){
registerDisposableBean(beanName,new DisposableBeanAdapter(bean,beanName,beanDefinition));
}
}
}
- 测试
- spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="car" class="org.springframework.test.ioc.bean.Car" scope="prototype"> <property name="brand" value="porsche"/> </bean> </beans>- 测试代码
public class PrototypeBeanTest { @Test public void testPrototype() throws Exception { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:prototype-bean.xml"); Car car1 = applicationContext.getBean("car", Car.class); Car car2 = applicationContext.getBean("car", Car.class); Assert.isFalse(car1==car2); } }
- FactoryBean FactoryBean接口主要用于标识一个bean是不是FactoryBean对象,如果是,则获取该对象的时候,会从一个Map缓存中获取,如果缓存不存在,则从FactoyBean的getObject方法中得到一个对象,主要代码如下:
private final Map<String, Object> factoryBeanObjectCache = new HashMap<>();
@Override
public Object getBean(String beanName) throws BeansException {
//如果已经存在该bean,则直接调用方法返回
Object sharedInstance = getSingleton(beanName);
if(sharedInstance!=null){
//如果是FactoryBean,从FactoryBean#getObject中创建bean
return getObjectForBeanInstance(sharedInstance,beanName);
}
BeanDefinition beanDefinition = getBeanDefinition(beanName);
Object bean = createBean(beanName, beanDefinition);
return getObjectForBeanInstance(bean,beanName);
}
protected Object getObjectForBeanInstance(Object beanInstance,String beanName){
Object object = beanInstance;
if(beanInstance instanceof FactoryBean){
FactoryBean factoryBean = (FactoryBean)beanInstance;
try{
if(factoryBean.isSingleton()){
//singleton作用域bean,从缓存中获取
object = this.factoryBeanObjectCache.get(beanName);
if(object==null){
object = factoryBean.getObject();
this.factoryBeanObjectCache.put(beanName,object);
}
}else{
//prototype作用域bean,新创建bean
object = factoryBean.getObject();
}
}catch (Exception ex) {
throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", ex);
}
}
return object;
}
- FactroyBean实例如下,往泛型中存入Car对象,然后提供getObject方法:
public class CarFactoryBean implements FactoryBean<Car> {
private String brand;
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setBrand(brand);
return car;
}
@Override
public boolean isSingleton() {
return true;
}
public void setBrand(String brand){
this.brand = brand;
}
}
总结:以上是Spring中常用的三种东西实现方法,具体代码看开头代码链接。