基于XML的Spring

一、概述

Spring是一个轻量级开源框架

两大核心

  • 控制反转(IoC)
  • 面向切面编程(AOP)

1.1Spring的优势

  • 方便解耦:提供IoC容器管理对象,避免程序过度耦合
  • AOP编程支持:方便进行面向切面的编程
  • 声明式事务的支持:从单调烦闷的事务代码中解脱,通过声明方式对事务进行管理,提高开发效率和质量
  • 集成各种框架:Spring 整合各种框架,降低框架的使用难度
  • 方便测试:简化测试的代码
  • 源码学习:Spring 的源代码设计精妙,对 Java 设计模式灵活运用,是 Java 技术的最佳实践的范例

MVC架构图:

Spring可以用于表现层、业务层、持久层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3TfKTFWN-1589725573536)(image/三层架构.png)]

1.2 耦合

1.2.1什么是耦合

程序的耦合:程序间的依赖关系

包括:

  •          类之间的依赖
    
  •          方法间的依赖
    

解耦:

  •  降低程序间的依赖关系
    
  •  编译期不依赖,运行时才依赖
    

解耦的思路:

  •      第一步:使用反射来创建对象,而避免使用new关键字
    
  •      第二步:通过读取配置文件来获取要创建的对象全限定类名
    

开发中力争做到高内聚低耦合

public static void main(String[] args) throws Exception {
   
        //1、加载驱动
        DriverManager.deregisterDriver(new com.mysql.cj.jdbc.Driver());
        //2、获取连接
        Connection connection =
                DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/spring?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true"
                        , "root", "root123");
        //3、获取操作表对象
        String sql = "select `name` from `account`";
        PreparedStatement ps = connection.prepareStatement(sql);
        //4、执行SQL语句
        ResultSet rs = ps.executeQuery();
        //5、遍历结果集
        while (rs.next()){
   
           String name = (String) rs.getObject("name");
            System.out.println(name);
        }
        //6、关闭资源
        rs.close();
        ps.close();
        connection.close();
    }

上述代码:

依赖了数据库的具体驱动类(MySQL),如果这时候更换了数据库品牌(比如 Oracle),需要修改源码来重新数据库驱动。若是没有这个驱动类,编程时就会报错,所以耦合很强

1.2.2 程序解耦的思路

解决耦合:

Class.forName("com.mysql.cj.jdbc.Driver");

使用反射来加载驱动。此时,需要的只是一个字符串,不再依赖一个具体的驱动类,就算删除 mysql 的驱动 jar 包,依然可以编译

1.2.3 工厂模式解耦

Class.forName(“com.mysql.cj.jdbc.Driver”)中驱动的全限定类名在程序中写死的,一旦要改还是要修改源码,引出工厂模式解决,通过读取配置文件路径读取驱动名,然后反射加载驱动

工厂模式:

在实际开发中,可以把三层的对象都使用配置文件配置起来,当程序运行时,让一个工具类通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。

那么,这个读取配置文件,创建和获取三层对象的工具类就是工厂

properties文件

accountService=com.json.service.AccountService
accountDao=com.json.dao.AccountDao

工厂模式创建对象

/*
 *	 一、需要一个配置文件来配置我们的service和dao
 *           配置的内容:唯一标识=全限定类名(key=value)
 *   二、通过读取配置文件中配置的内容,反射创建对象
 *
 *   配置文件可以是xml也可以是properties
*/

public class BeanFactories {
   

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

    static {
   
        try {
   
        	properties = new Properties() ;
        	beans = new HashMap<String, Object>();
       		InputStream in = BeanFactories.class.getClassLoader().getResourceAsStream("bean.properties");
        	//加载properties配置文件
            properties.load(in);
            //取出配置文件中所有的Key
            Enumeration<Object> keys = properties.keys();
            while(keys.hasMoreElements()){
   
                //取出每个Key
                String beanName = (String) keys.nextElement();
                //根据key获取value
                String beanPath = properties.getProperty(beanName);
                //反射创建对象
                Object bean = Class.forName(beanPath).newInstance();
                //把key和value存入容器中
                beans.put(beanName, bean);
            }
        } catch (Exception e) {
   
            throw new ExceptionInInitializerError("创建工厂失败");
        }
    }

    //根据bean的名称获取对象
    public static Object getBean(String beanName){
   
        return beans.get(beanName);
    }
}

模拟表现层

public class AccountController {
   

    /**
     * 模拟保存账号的表现层
     * @param args
     */
    public static void main(String[] args) {
   
        AccountService accountService = (AccountService) BeanFactories.getBean("accountService");
        accountService.save();
    }
}

模拟业务层

public class AccountService {
   

    private AccountDao accountDao = (AccountDao) BeanFactories.getBean("accountDao");

    public void save(){
   
        accountDao.saveAccount();
    }
}

模拟持久层

public class AccountDao {
   

    public void saveAccount(){
   
        System.out.println("模拟保存账号");
    }
}

如此,service、dao获取对象则不再依赖一个具体的类,而是通过唯一标识的字符串,通过反射创建对象

二、控制反转

由于需要存储很多对象,需要利用集合Map和List,选择Map或List在于是否有查找需求,有查找需求,选Map

在程序运行时,创建一个Map存放对象,称之为容器

获取对象的方式:

  • 常规:获取对象时,都是采用new的方式,是主动的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2taeXA1j-1589725573540)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1585022853948.png)]

  • 控制反转:利用工厂从容器中获取指定的对象,这时获取对象的方式发生了改变,是被动的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E6SqULyZ-1589725573542)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1585022870490.png)]

这种被动的获取对象的思想就是控制反转

控制反转(Inversion of Control)

  • 依赖注入(Dependency Injection)
  • 依赖查找(Dependency Lookup)

IoC的作用:削减程序中的耦合(解除代码中的依赖关系)

三、IOC容器

基于XML的配置步骤开发

  1. 导入Spring的核心jar

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7AvDVlNl-1589725573544)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1585023448501.png)]

  2. 创建XML文件(application.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="accountDao" class="com.json.dao.AccountDao"></bean>
    
        <bean id="accountService" class="com.json.service.AccountService"></bean>
    
    
    </beans>
    
  3. 测试是否配置成功

    	public static void main(String[] args) {
         
            //ApplicationContext对象为上下文对象(可以认为该对象为IOC容器),用于连接xml配置文件与java代码
            ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
            //根据id获取Bean对象(方式一)
            AccountService accountService = (AccountService) context.getBean("accountService") ;
           //根据id获取Bean对象(方式二)
            AccountDao accountDao = context.getBean("accountDao",AccountDao.class);
    
        }
    
  4. 运行结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nA14mwzg-1589725573545)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1585025224884.png)]

3.1 ApplicationContext对象

一般称BeanFactory为IoC容器,而称ApplicationContext为应用上下文 ,ApplicationContext是连接xml配置文件与程序的对象

可以解析xml配置文件,获取IOC容器中的对象供程序使用

ApplicationContext的三个常用实现类:

  • ClassPathXmlApplicationContext
    • 加载类路径下的配置文件,要求配置文件必须在类路径下(推荐使用)
  • FileSystemXmlApplicationContext
    • 加载磁盘任意路径下的配置文件(必须有访问权限)
  • AnnotationConfigApplicationContext:
    • 用于读取注解(配置类)创建容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L57siSMj-1589725573546)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1585026213748.png)]

3.2 BeanFactory对象

  • BeanFactory和ApplicationContext是Spring的两大核心接口,而其中ApplicationContext是BeanFactory的子接口,它们都可以当做Spring的容器,Spring容器是生成Bean实例的工厂,并管理容器中的Bean
  • 一般称BeanFactory为IOC容器,而称ApplicationContext为应用上下文
  • BeanFactory是Spring最底层的接口,提供了最简单的容器的功能,只提供了实例化对象和获取对象的功能

BeanFactory与ApplicationContext的区别

BeanFactory ApplicationContext
功能 实例化对象、获取对象 国际化、访问资源,如URL和文件、消息发送、响应机制、AOP(拦截器)、实例化对象、获取对象
创建对象方 式 延迟加载(获取对象时才创建) 立即加载(读取完配置文件马上就创建)
单例/多例 多例对象 单例对象
	public static void main(String[] args) {
   
       //加载配置文件时,立即创建所有的Bean对象实例 ,且每个Bean对象默认是单例
       ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
       AccountService accountService = (AccountService) context.getBean("accountService") ;

        
        Resource resource = new ClassPathResource("application.xml");
        BeanFactory beanFactory = new XmlBeanFactory(resource);
        //只要获取Bean时,才创建对应的Bean,且为多例
        AccountDao accountDao = beanFactory.getBean("accountDao",AccountDao.class);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mHOjefjt-1589725573547)(C:\Users\333\AppData\Roaming\Typora\typora-user-images\1585027984714.png)]

3.3 Bean

作用:用于配置对象让 Spring 来创建的。默认情况下调用无参构造函数。如果没有无参构造函数则不能创建成功

3.3.1 bean标签

属性:

  • id:给对象在容器中提供一个唯一标识,用于获取对象
  • class:类的全限定类名,用于反射创建对象。默认情况下调用无参构造函数
  • scope:对象的生命周期
    • singleton:默认值,单例(容器创建就创建Bean)
    • prototype:原型,多例(具体获取时才创建Bean)
    • request:Spring 创建一个 Bean 的对象,将对象存入到 request 域中
    • session:创建一个 Bean 的对象,将对象存入到 session 域中
    • global-session:创建一个 Bean 的对象,存放于Context域中
  • init-method:指定类中的初始化时执行的方法
  • destroy-method:指定类中的销毁时执行方法(销毁容器时才执行)
  • lazy-init:懒加载(具体获取时才创建Bean)

创建、初始化、销毁

public class AccountService {
   

   public AccountService(){
   
       System
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值