美文网首页
02-Spring-IOC

02-Spring-IOC

作者: XAbo | 来源:发表于2020-12-23 13:01 被阅读0次

IOC:控制反转:将对象的创建权由Spring管理。 降低依赖关系

一、模拟IOC

利用工厂模式模拟实现IOC:使用工厂模式创建services和dao

配置文件:bean.properties

accountDao=com.examples.dao.AccountDaoImpl
accountServices=com.examples.services.AccountServicesImpl

BeanFactory:

public class BeanFactory {

    // 使用原生的不好用,Properties的load是无序的,使用子类进行有序保存到集合Properties 
    //private  static Properties props;
    private  static OrderedProperties props;
    private  static Map<String ,Object> beans;
    static {
         props =  new OrderedProperties();
        //InputStream  in =  new FileInputStream(); 这个方式不合适。
        //InputStream  in =  this.getClass().getResourceAsStream("bean.properties");  this不能放在static
        InputStream   in =  BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");

        try {
            props.load(in);
            beans = new HashMap<String ,Object>();
            Enumeration  keys = props.keys();
            while (keys.hasMoreElements()){
                String  key = keys.nextElement().toString();
                String  beanPath =  props.getProperty(key);
                Object  value = Class.forName(beanPath).newInstance();
                beans.put(key,value);
            }
        } catch (Exception e) {
            throw  new ExceptionInInitializerError("初始化失败,不存在配置文件");
        }
    }
    public static Object getBean(String  beanName){
           return  beans.get(beanName);
    }
}

OrderedProperties:

public class OrderedProperties extends Properties {
    private static final long serialVersionUID = -4627607243846121965L;
    private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();
    public Enumeration<Object> keys() {
        return Collections.enumeration(keys);
    }
    public Object put(Object key, Object value) {
        keys.add(key);
        return super.put(key, value);
    }
    public Set<Object> keySet() {
        return keys;
    }
    public Set<String> stringPropertyNames() {
        Set<String> set = new LinkedHashSet<String>();

        for (Object key : this.keys) {
            set.add((String) key);
        }
        return set;
    }
}

services层
AccountServicesImpl:

public class AccountServicesImpl implements AccountServices {
    //耦合度过低,依赖性过强
    //private AccountDao accountDao = new AccountDaoImpl();
     private  AccountDao accountDao =(AccountDao) BeanFactory.getBean("accountDao");
    @Override
    public void saveAccount() {
        accountDao.saveAccount();
    }
}

dao层
AccountDaoImpl:

public class AccountDaoImpl implements AccountDao {
    @Override
    public void saveAccount() {
        System.out.println("DAO---保存账户数据");
    }
}

客户端

public class client {
    public static void main(String[] args) {
        //耦合度过低,依赖性过强
        //AccountServices  accountServices = new AccountServicesImpl();
        AccountServices  accountServices = (AccountServices) BeanFactory.getBean("accountServices");
        accountServices.saveAccount();
    }
}

二、 Spring的IOC

bean的创建方式

2.1 Spring生产Bean

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">
     <!--把对象的管理交给Spring,内容与bean.properties中的配置一致-->
    <bean id="accountDao" class="com.myspring.dao.AccountDaoImpl"></bean>
    <bean id="accountServices" class="com.myspring.services.AccountServicesImpl"></bean>
</beans>
public class client {
    public static void main(String[] args) {
        ApplicationContext  ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
        AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
        AccountDao accountDao = ApplicationContext.getBean("accountDao",AccountDao.class);
        System.out.println(accountServices.toString()+"||"+accountDao.toString());
       }
}

ApplicationContextApplicationContext相比 BeanFactory在其基础上扩展了功能。如:事件通知(ApplicationEventPublisher接口),该接口定义了事件的发布机制;可参考:https://blog.51cto.com/wjzxp/5421639

ApplicationContext的继承关系

Spring基于ApplicationContextBeanFactory加载的对象的方式不同:

  • 多例模式下使用BeanFactory(延迟加载配置文件中的对象);
  • 单例模式下使用ApplicationContext(立即加载配置文件中的对象);

ApplicationContext和BeanFactory加载配置文件方式区别:

BeanFactory:Resource。
ApplicationContext:
1.ClassPathXmlApplicationContext:可以加载类路径下的配置文件。
2.FileSystemXmlApplicationContext:可以加载磁盘任意路径下的有访问权限的文件。
3.AnnotationConfigApplicationContext:读取注解创建容器。

2.2 Spring对Bean的管理。

Spring主要管理Bean的内容:
1.创建Bean对象的方式
2.bean对象的作用范围
3.bean对象的生命周期

1.创建Bean对象的方式

1.1创建Bean对象的方式:构造方法。

<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
       2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">
   
    <!--<bean id="accountDao" class="com.myspring.dao.AccountDaoImpl"></bean>-->
    <!-- 第一种:使用默认的构造方法:在配置文件中使用Bean标签,
         配置id和class属性之后,且没有其他属性和标签时,如果该类中没有默认的构造方法,则无法创建对象。-->
 <bean id="accountServices" class="com.myspring.services.AccountServicesImpl"></bean> 
</beans>

1.2.创建Bean对象的方式:工厂类提供的方法。

<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
       2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">
      
    <!-- 第二种:使用普通工厂中的方法创建的对象(使用某个类中的方法创建对象并存入Spring容器)-->
   <bean id="InstanceFactory" class="com.myspring.demos.InstanceFactory"></bean>
   <bean id="accountServices" factory-bean="InstanceFactory" factory-method="getAccountServices"></bean>
    
</beans>

工厂类 InstanceFactory

/*模拟jar包中的工厂类 InstanceFactory.class
* */
public class InstanceFactory {
    public AccountServices getAccountServices(){
        System.out.println("我是工厂类");
        return new AccountServicesImpl();
    }
}

1.3.创建Bean对象的方式:工厂类提供的静态方法。

<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
       2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">
      
 <!-- 第三种:使用工厂中的静态方法创建的对象(使用某个类中的静态方法创建对象并存入Spring容器)
       factory-method:不写这个属性的时候,就跟第一个是一致,然而StaticFactory类中不一定有可用的构造方法。-->

    <bean id="accountServices" class="com.myspring.demos.StaticFactory" factory-method="getAccountServices"></bean>
    
</beans>

工厂类:StaticFactory

/*模拟jar包中的工厂类StaticFactory.class
 * */
public class StaticFactory {
    public static AccountServices getAccountServices(){
        System.out.println("我是静态方法");
        return new AccountServicesImpl();
    }
}

通用客户端:

public class client {
    public static void main(String[] args) {
        ApplicationContext  ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
        AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
        System.out.println(accountServices.toString());
    }
}

2.Bean对象的作用范围

<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
               2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">
       <!-- scope的取值:
          singleton:单例 
          prototype:多例
          request:作用于WEB应用的请求范围
          session:作用于WEB应用的会话范围
         global-session:集群模式下的会话范围(全局会话范围),非集群就是session范围。
      -->

    <bean id="accountServices" class="com.myspring.services.AccountServicesImpl" scope="singleton"></bean>
 </beans>

3.Bean对象的生命周期

<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
       2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
  -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd">
 
     <bean id="accountServices" class="com.myspring.services.AccountServicesImpl" 
      scope="singleton" init-method="init" destroy-method="destory"></bean>
</beans>

AccountServicesImpl:

public class AccountServicesImpl implements AccountServices {
    //这里是有参参构造方法
    public  AccountServicesImpl(){
        System.out.println("构造……");
    }
    @Override
    public void saveAccount() {
        System.out.println("services");
    }
    public void init(){
        System.out.println("init……");
    }
    public void destory(){
        System.out.println("destory……");
    }
}

客户端:

public class client {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext  ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
        AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
        System.out.println(accountServices.toString());
        ApplicationContext.close();
        System.out.println("close----");
    }
}

单例结果:

单例结果.png

多例结果:

多例结果.png

相关文章

  • 02-Spring-IOC

    IOC:控制反转:将对象的创建权由Spring管理。 降低依赖关系。 1.1模拟的IOC 利用工厂模式模拟实现IO...

网友评论

      本文标题:02-Spring-IOC

      本文链接:https://www.haomeiwen.com/subject/vyisnktx.html