Spring框架----IOC的概念和作用之工厂模式

38 篇文章 1 订阅
23 篇文章 2 订阅

创建bean对象的工厂

bean在计算机英语中,有可重用组件的含义
可重用:可反复使用。组件:组成部分,比如service可以被servlet反复使用,dao被service使用。service可以看成是可重用的组成部分。
javabean>=实体类,用Java语言编写的可重用组件
bean对象的工厂它就是创建service和dao对象的
如何创建:
第一个需要一个配置文件来配置我们的service和dao
配置的内容:全限定类名,唯一标识(key-value)(用于取到这个类)
第二个通过读取配置文件中配置的内容,反射创建对象
我的配置文件可以时xml也可以时properties,properties较为简单
bean.properties

accountService=com.yujie.service.Impl.AccountServiceImpl
accountDao=com.yujie.dao.dao.Impl.AccountDaoImpl
public class BeanFactory {
    //定义一个properties对象
    private static Properties props;

    //使用静态代码块为properties对象赋值
    static{
        try {
            //实例化对象
            props = new Properties();         //降低,而不是消除
            //获取properties文件的流对象,类加载器是动态获取文件的绝对路径
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");       //获取配置文件
            props.load(in);               //读取流
        }catch (Exception e){
            throw new ExceptionInInitializerError("初始化properties失败")
        }
    }
    //这里不能写死了某个类名
    //根据bean的名称获取bean对象,通过读取配置文件的方式完成反射
    public static Object getBean(String beanName){
        Object bean=null;
        try {
            String beanPath = props.getProperty(beanName);        //通过beanname来得到bean的路径
            bean = Class.forName(beanPath).newInstance();         //通过反射机制来获取对象
        }catch(Exception e){
            e.printStackTrace();
        }
        return bean;
    }
    
}

能不能解耦呢?下面改装一下,实现解耦

public class Client {
    public static void main(String[] args) {
//        IAccountService as=new AccountServiceImpl();
        IAccountService as=(IAccountService)BeanFactory.getBean("accountService");
        as.saveAccount();
    }
}
public class AccountServiceImpl implements IAccountService {
//    private IAccountDao accountDao=new AccountDaoImpl();
    private IAccountDao accountDao=(IAccountDao) BeanFactory.getBean("accountDao");
    public void saveAccount() {
        accountDao.saveAccount();
    }
}

这个就是工厂模式解耦,我们把accountDao给删掉,编译时没问题,运行时才报错在这里插入图片描述
这就是工厂模式解耦
但是这个代码仍然有问题,

for(int i=0;i<5;i++){
    IAccountService as=(IAccountService)BeanFactory.getBean("accountService");
    System.out.println(as);
}

在这里插入图片描述
打印出来了5个对象,这时候对象是多例的,单例对象是说从始至终只有一个对象实例。他们有什么区别呢,
在serviceImpl中,i是一个类的成员,方法操作类成员的属性

private int i=1;
public void saveAccount() {
    accountDao.saveAccount();
    System.out.println(i);
    i++;
}

在这里插入图片描述
这时候i一直是1,不管有多少个service访问的时候,都是1。
如果是单例的话,此时每个编码都应该相同,比如5个都是com.yujie.service.Impl.AccountServiceImpl@74a14482
只被创建一次,从而类中的成员也就只会初始化一次。所以多个线程访问,多个对象访问时,由于对象的实例只有一个,类成员在方法能够进行改变的时候,单例就出现了。
多例对象对象被创建多次,其执行效率没有单例对象高
单例对象有线程问题,但是在我们service和dao中,没有类的方法对其类的属性进行调整,而是会把属性定义到方法中去,每次方法都会对他重新初始化,也能保证每次得到的都是1。
所以我们需要每次都是同一个对象,由于beanfactory创建对象的时候调用的时newInstance,每次都会调用默认构造函数创建对象。调整的前提是,我们的newInstance只能一次,如果创建了不存起来,Java的垃圾回收机制就会长时间不用时回收。所以在对象创建起来之后就要存起来
我们需要存储这些对象的,我们称之为容器

定义一个Map,用于存放我们要创建的对象,我们把它称之为容器

public class BeanFactory {
    //定义一个properties对象
    private static Properties props;

    //定义一个Map,用于存放我们要创建的对象,我们把它称之为容器
    private static Map<String,Object> beans;

    //使用静态代码块为properties对象赋值,静态代码块只在类加载的时候执行一次
    static{
        try {
            //实例化对象
            props = new Properties();         //降低,而不是消除
            //获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");       //获取配置文件
            props.load(in);               //读取流
            //用hashMap实例化容器
            beans=new HashMap<String, Object>();
            //取出配置文件中所有的key
            Enumeration keys=props.keys();
            //遍历枚举
            while(keys.hasMoreElements()){
                //取出每个key
                String key=keys.nextElement().toString();
                //根据key获取value
                String beanPath=props.getProperty(key);
                //反射创建对象
                Object value=Class.forName(beanPath).newInstance();
                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch (Exception e){
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }
    //根据bean的名称获取对象,这个对象时单例的
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

此时输出结果如上,当多个人在使用它访问时,此时就时单线程。第一个人再修改,后面的也跟着看到修改的结果,但是持久层和业务层不要定义可修改的类成员

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值