栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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;


public interface FactoryBean {
    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;


public class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {
    private final Map 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 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;


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;


public class ProxyBeanFactory implements FactoryBean {

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

            Map 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接口测试完成

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/852381.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号