Spring手撸源码系列-FactoryBean的实现和使用

这章咱们来实现FactoryBean,是FactoryBean不是BeanFactory啊,话说,是有多敬业多好的产品,有了BeanFactory还想出来了FactoryBean,

BeanFactory是将将某个类注册到bean容器工厂里

FactoryBean也是一样的功能,唯一不同的是通过实现ioc提供的一个接口,我们系统或者我们自己的类实现此接口,可以做一些自己想要的功能然后返回给IOC容器里的操作

首先我们这次要添加两个类,一个是FactoryBean,用来让用户进行实现的接口,第二个是要添加一个FactoryBeanRegistrySupport类,专门用来处理Factory的支持类FactoryBean注册获取等操作,还要修改一个类,修改下AbstractBeanFactory类文件,将如果是FactoryBean实现类就反馈,不是就走BeanFactory那一套操作。那接下来就上代码把

1.代码实现

1.创建FactoryBean接口,提供3个方法,获取对象、对象类型,以及是否是单例对象,如果是单例对象依然会被放到内存中

package com.spring.sourcecode.springframework.beans.factory;

/**
 * @Author df
 * @Date 2022/4/30 10:54
 * @Version 1.0
 */
public interface FactoryBean<T> {
    T getObject() throws Exception;

    Class<?> getObjectType();

    boolean isSingleton();
}

2.主要处理的就是关于 FactoryBean 此类对象的注册操作,也定义了缓存操作 factoryBeanObjectCache,用于存放单例类型的对象,避免重复创建,整体的核心逻辑就是注册获取。

package com.spring.sourcecode.springframework.beans.factory.support;

import com.spring.sourcecode.springframework.beans.BeansException;
import com.spring.sourcecode.springframework.beans.factory.FactoryBean;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author df
 * @Date 2022/4/30 11:31
 * @Version 1.0
 */
public class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>();

    // 从容器里取出数据
    protected Object getCachedObjectForFactoryBean(String beanName) {
        Object object = this.factoryBeanObjectCache.get(beanName);
        return (object != NULL_OBJECT ? object : null);
    }

    protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName) {
        if (factory.isSingleton()) {
            // 是单例从容器中取出来
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // 容器中取不到从factory实现类里去获取
                object = doGetObjectFromFactoryBean(factory, beanName);
                this.factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT);
            }
            return (object != NULL_OBJECT ? object : null);
        } else {
            return doGetObjectFromFactoryBean(factory, beanName);
        }
    }

    // 从FactoryBean实现类里获取对象
    private Object doGetObjectFromFactoryBean(final FactoryBean factory, final String beanName) {
        try {
            return factory.getObject();
        } catch (Exception e) {
            throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
        }
    }


}

3.修改AbstractBeanFactory类,主要是更改doGetBean方法里返回bean的方式,通过getObjectForBeanInstance()添加此方法用来区分是正常bean还是FactoryBean,此类就使用了FactoryBeanRegistrySupport,所以需要在继承类里修改下继承FactoryBeanRegistrySupport就可以了

 protected <T> T doGetBean(final String name, final Object[] args) {
        // 获取单例bean
        Object sharedInstance = getSingleton(name);
        if (sharedInstance != null) {
            return (T) getObjectForBeanInstance(sharedInstance, name);
        }
        BeanDefinition beanDefination = getBeanDefinition(name);
        Object bean = createBean(name, beanDefination, args);
        return (T) getObjectForBeanInstance(bean, name);
    }

    private Object getObjectForBeanInstance(Object beanInstance, String beanName) {
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }
        // 容器中是否获取的到
        Object object = getCachedObjectForFactoryBean(beanName);
        if (object == null) {
            FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance;
            object = getObjectFromFactoryBean(factoryBean, beanName);
        }
        return object;
    }

2.测试准备

添加IUserDao,

public interface IUserDao {
    String queryUserName(String uId);
}

 添加UserService,userService里使用了IUserDao

package com.spring.sourcecode.springframework.test;

import com.spring.sourcecode.springframework.beans.factory.*;
import com.spring.sourcecode.springframework.context.ApplicationContext;
import com.spring.sourcecode.springframework.context.ApplicationContextAware;

/**
 * @Author df
 * @Date 2021/11/8 10:14
 * @Version 1.0
 */
public class UserService {
    private String uId;
    private String company;
    private IUserDao userDao;
    private String location;


    public String queryUserInfo() {
        return userDao.queryUserName(uId) + "," + company + "," + location;
    }

    public String getuId() {
        return uId;
    }

    public void setuId(String uId) {
        this.uId = uId;
    }

    public IUserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(IUserDao userDao) {
        this.userDao = userDao;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

}

 添加了实现了FactoryBean的ProxyBeanFactory类,就可以做我们自己用户该做的事情了

package com.spring.sourcecode.springframework.bean;

import com.spring.sourcecode.springframework.beans.factory.FactoryBean;
import com.spring.sourcecode.springframework.test.IUserDao;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author df
 * @Date 2022/4/30 14:26
 * @Version 1.0
 */
public class ProxyBeanFactory implements FactoryBean<IUserDao> {

    @Override
    public IUserDao getObject() throws Exception {
        InvocationHandler handler = (proxy, method, args) -> {

            Map<String, String> hashMap = new HashMap<>();
            hashMap.put("10001", "阿三");
            hashMap.put("10002", "阿水");
            hashMap.put("10003", "阿绿");

            return "你被代理了 " + method.getName() + ":" + hashMap.get(args[0].toString());
        };
        return (IUserDao) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{IUserDao.class}, handler);
    }

    @Override
    public Class<?> getObjectType() {
        return IUserDao.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

3.测试

单元测试

public class ApiTest {
    //
    @Test
    public void testFactoryBean() {
        // 1.初始化BeanFactory
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
        applicationContext.registerShutdownHook();

        // 2.获取bean对象调用方法
        UserService userService = applicationContext.getBean("userService", UserService.class);
        System.out.println("测试结果:" + userService.queryUserInfo());
    }
}

 执行完成,FactoryBean接口测试完成

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值