[技术分享]谈谈我对BeanFactory理解

文章介绍了BeanFactory的概念,它是用来管理Bean的容器,特别是无状态对象。文章通过示例展示了如何初始化BeanFactory,以及如何使用反射和注解来自动化处理Bean的实例化和管理,从而简化大量Bean的配置工作。此外,还讨论了如何通过全局扫描和@Bean注解来自动加载类到BeanContext中。
摘要由CSDN通过智能技术生成

BeanFactory

IOC

ioc是指(Inversion of Control)也就是控制反转。
在设计模式中有一种模式叫做单例模式,如果对于一个类只作于方法调用而不保存任何状态的,我们就一般只创建一个对象用过来使用,这种模式就叫单例模式。

例如

1.有状态的
@Data
public class User{
	private String name;
	private Interage age;
}

这种user类创建出来的对象就是有状态的。

2.无状态的
public class UserService{
	public Reuslt login(...){
			....
	}
}

这样的类创建出来的对象只用于做方法调用的就是无状态的。

Bean

Bean就是描述Java的软件组件模型,一般是代表那种无状态的类的对象,在项目启动前就new了Bean对象并且放到了容器里面,需要用的时候就从容器里取

Bean容器

一般是存放Bean的一个Map集合,可以在项目启动前调用一个init()方法如下面代码

public class BeanFactory {
    private  Map<Class<?>,Object> beanContext;
    public  Map<Class<?>, Object> getBeanContext() {
        if(beanContext==null)beanContext=new HashMap<>();
        return beanContext;
    }
    public  void putBean(Class<?> clazz,Object o){
        if(beanContext==null)beanContext=new HashMap<>();
        beanContext.put(clazz,o);
    }
    public  void  setBeanContext(Map<Class<?>, Object> context) {
        beanContext= context;
    }
    public   <T> T getBean(Class<T> clazz) {
        if(beanContext==null||(!beanContext.containsKey(clazz)))return null;
        return (T)beanContext.get(clazz);
    }

}

将Bean的对象存放在BeanContext里面,如果需要用的时候就调用getBean方法就能获取到Bean对象了。

例子:

比如我们现在有个Bean类叫UserService

public class UserService{
	.....
}

那么我们的init方法可以这样写

public class PojectInit{
	public BeanFactory init(){
		BeanFactory beanFactory = new BeanFactory();
		beanFactory.put(UserService.class,new UserService());
		return beanFactory;
	}
}

这样就能将东西全部放进去了

反射

虽然BeanFactory很好,但是如果我的Bean多了怎么办,那么我岂不是要写很多的beanFactory.put();
为了解决这个问题,我们可以采用一下java的反射机制,配合注解去使用
我们可以定义一个Bean注解

@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Bean {
}

当我们想设置一个类为Bean类的话我们可以这样写

@Bean
public class UserService{
	.....
}

接下来就是下一个问题,我们如何将带有@Bean的类实例化放入BeanContext呢,当然是全局扫描

public class PojectInit{
	public BeanFactory init(Class<?> clazz){
		BeanFactory beanFactory=new BeanFactory();
        String[] split = clazz.getName().split("\\.");

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < split.length-1; i++) {
            sb.append(split[i]).append(".");
        }
        if(sb.charAt(sb.length()-1)=='.')sb.deleteCharAt(sb.length()-1);
        classpath=sb.toString();
        String path = Objects.requireNonNull(clazz.getResource("")).getPath();
        initBean(new File(path));
        return beanFactory;
	}
	 private  void initBean(File file){
        if(file.isDirectory()){
            File[] files = file.listFiles();
            assert files != null;
            for (File pathFile : files) {
                if (pathFile.isDirectory()) {
                    initBean(pathFile);
                    continue;
                }
                if (pathFile.getName().contains(".class")) {
                    String className = pathFile.getPath().substring(pathFile.getPath().indexOf(classpath)).replace(".class", "").replace("\\", ".");
                    try {
                        Class<?> obj = Class.forName(className);
                        if (!isBean(obj)) {
                            continue;
                        }
                        if(obj.isAnnotation()){
                            continue;
                        }
                        if(obj.isInterface()){
                            beanFactory.putBean(obj,null);
                            //执行接口方法
                            continue;
                        }
                        if(!obj.isPrimitive()){

                            Class<?>[] interfaces = obj.getInterfaces();
                            if(interfaces.length>0){
                                beanFactory.putBean(interfaces[0],obj.newInstance());
                            }else {
                                beanFactory.putBean(obj,obj.newInstance());
                            }
                        }
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                        e.printStackTrace();
                    }

                }
            }
        }
    }
    private boolean isBean(Class<?> clazz){
        return isAnnotation(clazz, Bean.class);
    }
     private boolean isAnnotation(Annotation annotation, List<Class<?>> list, Class<? extends Annotation> annotationClazz){
        if (annotation.annotationType().getAnnotation(annotationClazz)!=null)return true;
        if(list.contains(annotation.annotationType()))return false;
        list.add(annotation.annotationType());
        Class<?> annotationType = annotation.annotationType();
        Annotation[] annotations = annotationType.getDeclaredAnnotations();
        boolean flag=false;
        for (Annotation an : annotations) {
            flag=flag||isAnnotation(an,list,annotationClazz);
        }
        return flag;
    }
    private boolean isAnnotation(Class<?> clazz,Class<? extends Annotation> annotationClazz){
        if (clazz.getAnnotation(annotationClazz)!=null)return true;
        boolean flag= false;
        for (Annotation annotation : clazz.getDeclaredAnnotations()) {
            flag=flag|| AnnotationUtils.isAnnotation(annotation, new ArrayList<>(), annotationClazz);
        }
        return flag;
    }
}

main方法我们可以这样写

public class Main{
	public static void main(){
		BeanFactory beanFactory = new PojectInit().init(Main.class);
	}
}

这样就能得到一个BeanFactory的对象,里面就会自动去扫描@Bean的类。

代码可能有考虑不周到,现在目前在自己学习写Spring的东西,写的不是很好,欢迎各位评论和指点一下。
这个是我目前在学习Spring底层的时候自己的理解实现的代码,开源地址
https://github.com/WhiteEnzuo/StudySpring
我会不断的去更新内容和我的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怀特丶恩佐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值