使用spring的IOC解决程序耦合

使用springIOC解决程序耦合

官网:http://spring.io/

下载地址:

http://repo.springsource.org/libs-release-local/org/springframework/spring

解压:(Spring目录结构:)

* docs :API和开发规范.

* libs :jar包和源码.

* schema :约束.

 

 

 IOC入门

第一步:创建工程

 

第二步:导入spring的依赖包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>spring_day01_ioc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
    </dependencies>
</project>

 

第三步:创建Dao

创建接口AccountDao.java

/**
 * 账户的持久层接口
 */
public interface AccountDao {

    /**
     * 模拟保存账户
     */
    void saveAccount();
}
 

 

创建实现类AccountDaoImpl.java

/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl implements AccountDao {

    public  void saveAccount(){
        System.out.println("AccountDaoImpl 保存了账户");
    }
}

 

第四步:创建Service

创建接口AccountService.java

/**
 * 账户业务层的接口
 */
public interface AccountService {

    /**
     * 模拟保存账户
     */
    void saveAccount();
}
 

 

创建接口的实现类AccountServiceImpl.java

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao ;

    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }

    public void  saveAccount(){
System.out.println("AccountServiceImpl 保存了账户");
        accountDao.saveAccount();
    }
}
 

第五步:在resource下创建applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--把对象的创建交给spring来管理-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>

    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
</beans>

 

第六步:ApplicationContext接口对象

参考:ApplicationContext和ClassPathXmlApplicationContext、FileSystemXmlApplicationContex的关系。

【图例】

 

BeanFactory ApplicationContext 的区别 】(了解)

BeanFactory 才是Spring 容器中的顶层接口。

ApplicationContext 是它的子接口。

创建的方式都表示单例对象。

创建对象的时间点不一样。

ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。(立即加载)

BeanFactory:什么时候使用什么时候创建对象。(延迟加载)

 

ApplicationContext 接口的实现类

(1)ClassPathXmlApplicationContext: (重点)

它是从类的根路径下加载配置文件 推荐使用这种

(2)FileSystemXmlApplicationContext:

它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。

(3)AnnotationConfigApplicationContext: (第2天讲)

当我们使用注解配置容器对象时,需要使用此类来创建spring 容器。它用来读取注解。

测试类:

/**
 * 模拟一个表现层,用于调用业务层
 */
public class Client {

    // 模拟Action

//    /**
//     * 测试由ApplicationContext对象获取spring容器中创建的对象
//     * @param args
//     */
//    public static void main(String[] args) {
//        // 代码之间存在依赖关系(耦合)
//        // AccountService accountService = new AccountServiceImpl();
//        // 由spring创建对象(完成对象的解耦)
//        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//        // 通过名称调用(通过spring容器中的id属性)(推荐)
//        AccountService accountService = (AccountService) ac.getBean("accountService");
//        // 通过类型调用(通过spring容器中的class属性)
//        // AccountService accountService = ac.getBean(AccountServiceImpl.class);
//        accountService.saveAccount();
//    }

    /**
     * 测试BeanFactory和ApplicationContext之间的区别
     *
     * ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。(立即加载)
       BeanFactory:什么时候使,用什么时候创建对象。(延迟加载)
     */
//    public static void main(String[] args) {
//        // 使用ApplicationContext创建对象默认是单例(只要加载spring容器,对象会立即创建,叫做立即检索)
//        // ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//        // 使用BeanFactory创建对象默认是单例(当加载spring容器的时候,不会执行构造方法,对象不会立即创建,只要调用getBean的方法,对象才会创建,叫做延迟检索)
//        BeanFactory ac = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
//        AccountService accountService = (AccountService) ac.getBean("accountService");
//        System.out.println(accountService);
//
//        AccountService accountService1 = (AccountService) ac.getBean("accountService");
//        System.out.println(accountService1);
//    }

    /**
     * 【ApplicationContext 接口的实现类 】
     (1)ClassPathXmlApplicationContext:
     它是从类的根路径下加载配置文件 推荐使用这种
     (2)FileSystemXmlApplicationContext:
     它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。注意磁盘的权限
     (3)AnnotationConfigApplicationContext:
     当我们使用注解配置容器对象时,需要使用此类来创建spring 容器。它用来读取注解。
     */
    public static void main(String[] args) {
        // 测试ClassPathXmlApplicationContext
        // ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 测试FileSystemXmlApplicationContext
        ApplicationContext ac =  new FileSystemXmlApplicationContext("d:/applicationContext.xml");
        AccountService accountService = (AccountService) ac.getBean("accountService");
        System.out.println(accountService);
        AccountService accountService1 = (AccountService) ac.getBean("accountService");
        System.out.println(accountService1);
    }
}

 

 

 

 id和name的配置(了解)

id中不能出现特殊字符(容器中的唯一标识),name中可以出现特殊的字符(表示引用)。

可以指定多个name,之间可以用分号(“;”)、空格(“ ”)或逗号(“,”)分隔开,如果没有指定id,那么第一个name为标识符,其余的为别名; 若指定了id属性,则id为标识符,所有的name均为别名。如:

<bean name="alias1 alias2;alias3,alias4" id="hello1" class="com.zyh.spring3.hello.HelloWorld"> </bean>  

此时,hello1为标识符,而alias1,alias2,alias3,alias4为别名,它们都可以作为Bean的键值;

 

 实例化Bean的三种方式

 

创建工程

导入坐标:pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
</dependencies>
 

创建包,com.itheima.service,创建接口AccountService.java

/**
 * 账户业务层的接口
 */
public interface AccountService {

    /**
     * 模拟保存账户
     */
    void saveAccount();
}

 

创建包com.itheima.service.impl,创建接口的实现类AccountService.java

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements AccountService {

    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }

    public void  saveAccount(){
        System.out.println("service中的saveAccount方法执行了。。。");
    }

}

 

测试类:Client.java

public class Client {
    public static void main(String[] args) {
        //1.获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.根据id获取Bean对象
        AccountService as  = (AccountService)ac.getBean("accountService");
        as.saveAccount();
    }
}

 

 

第一种:采用无参数的构造方法方式实例化(用的最多)

applicationContext.xml

<!--创建Bean的三种方式 -->
<!-- 第一种方式:使用默认构造函数创建。
        在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
        采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>

需要无参的构造方法

public class AccountServiceImpl implements AccountService {
    //可以不写
    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }
}

第二种:采用静态工厂实例化的方式

applicationContext.xml

<!-- 第二种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器) -->
<bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>

AccountServiceImpl.java

public class AccountServiceImpl implements AccountService {

}

 

StaticFactory.java,静态工厂类

/**
 * 模拟一个工厂类(该类可能是存在于jar包中的,我们无法通过修改源码的方式来提供默认构造函数)
 */
public class StaticFactory {

    public static AccountService getAccountService(){
        return new AccountServiceImpl();
    }
}

 

第三种:采用实例工厂(非静态的)实例化的方式

applicationContext.xml

<!-- 第三种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器) -->
<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

 

AccountServiceImpl.java

public class AccountServiceImpl implements AccountService {

}

 

InstanceFactory.java

/**
 * 模拟一个工厂类(该类可能是存在于jar包中的,我们无法通过修改源码的方式来提供默认构造函数)
 */
public class InstanceFactory {

    public AccountService getAccountService(){
        return new AccountServiceImpl();
    }
}
 

总结:第一种无参构造的方式用的最多,第二种和第三种一般是调用spring底层写好类的时候会用到。

 

 Bean的作用访问的配置:scope的配置

Spring创建这个类的时候,默认采用的单例的模式进行创建的。如果想去改变单例模式,需要通过scope进行配置。

Scope属性中有以下几个取值:

  1. singleton                :默认值,单例的。
  2. prototype               :多例的。
  3. request                    :应用在web应用中,将创建的对象存入到request域中。
  4. session                   : 应用在web应用中,将创建的对象存入到session域中。
  5. globalsession          :应用在集群环境下使用。将创建的对象存入到全局的session中。

什么是globalsession(了解即可)?

 

applicationContext.xml中的配置

<!-- bean的作用范围调整
    bean标签的scope属性:
        作用:用于指定bean的作用范围
        取值: 常用的就是单例的和多例的
            singleton:单例的(默认值)
            prototype:多例的
            request:作用于web应用的请求范围
            session:作用于web应用的会话范围
            global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="prototype"></bean>

 

 Bean的生命周期的配置

单例对象
    出生:当容器创建时对象出生
    活着:只要容器还在,对象一直活着
    死亡:容器销毁,对象消亡
    总结:单例对象的生命周期和容器相同
多例对象  
    出生:当我们使用对象时spring框架为我们创建
    活着:对象只要是在使用过程中就一直活着。
    死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
    总结:多例对象的生命周期和对象是否被使用有关。与容器是否被销毁无关。

第一步:AccountServiceImpl.java

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements AccountService {

    public AccountServiceImpl(){
        System.out.println("对象创建了");
    }

    public void  saveAccount(){
        System.out.println("service中的saveAccount方法执行了。。。");
    }

    public void  init(){
        System.out.println("对象初始化了。。。");
    }
    public void  destroy(){
        System.out.println("对象销毁了。。。");
    }

}

 

第二步:applicationContext.xml

<!-- bean对象的生命周期
                单例对象
                    出生:当容器创建时对象出生
                    活着:只要容器还在,对象一直活着
                    死亡:容器销毁,对象消亡
                    总结:单例对象的生命周期和容器相同
                多例对象
                    出生:当我们使用对象时spring框架为我们创建
                    活着:对象只要是在使用过程中就一直活着。
                    死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收
                    总结:多例对象的声明周期和对象是否被使用有关
                -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"
      scope="singleton" init-method="init" destroy-method="destroy"></bean>

第三步:Client.java测试:

/**
 * 模拟一个表现层,用于调用业务层
 */
public class Client {

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        //1.获取核心容器对象
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.根据id获取Bean对象
        AccountService as  = (AccountService)ac.getBean("accountService");
        as.saveAccount();

        //手动关闭容器(单例的时候,关闭才有效果)
        ac.close();
    }
}

总结:开发场景

单例(常用):一般创建对象单例(例如Service对象、Dao对象,数据源的对象...)

多例:如果spring创建数据库连接对象Connection(每个线程使用的数据库连接对象是不同的,保证线程安全)

      Struts2(本身多实例,多线程),如果spring创建struts2的对象,一定是多例(了解)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值