zoukankan      html  css  js  c++  java
  • 23_1spring基础

    1.spring是什么

    2.spring的优势

    3.spring体系结构

    4.耦合

    程序间的依赖关系:类之间的依赖和方法之间的依赖。

    解构:降低程序间的依赖关系。

    实际开发中应该做到:编译期不依赖,实际运行期才依赖。

    解耦的思路:

      第一步:使用反射来创建对象,而避免使用new关键字。

      第二步:通过读取配置文件来获取要创建的对象的全限定类名。

    以下是注册驱动的一个例子,第一中方法,如果没有mysql包,编译都不能通过,而第二种方法,编译没有问题,运行时才会出现问题。

    package com.itheima.jdbc;
    
    import java.sql.*;
    
    /**
     * 程序的耦合
     */
    public class JDBCdemo1 {
        public static void main(String[] args) throws Exception {
            // 1.注册驱动
    //        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取连接
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/eesy", "root", "123456");
            // 3. 获取操作数据库的预处理对象
            PreparedStatement pstm = con.prepareStatement("select * from account");
            // 4.执行sql语句,得到结果集
            ResultSet rs = pstm.executeQuery();
            // 5.遍历结果集
            while (rs.next()){
                System.out.println(rs.getString("name"));
            }
            // 6.释放资源
            rs.close();
            pstm.close();
            con.close();
        }
    }

    4.1工厂模式解构

    第一步:创建接口和实现类

    package com.itheima.dao;
    
    /**
     * 账户的持久层接口
     */
    public interface IAccountDao {
        /**
         * 模拟保存账户
         */
        void saveAccout();
    }
    package com.itheima.dao.impl;
    
    import com.itheima.dao.IAccountDao;
    
    public class AccountDaoImpl implements IAccountDao {
        public void saveAccout() {
            System.out.println("保存了账户");
        }
    }
    package com.itheima.service;
    
    /**
     * 业务层的接口
     */
    public interface IAccountService {
        /**
         * 模拟保存账户
         */
        void saveAccount();
    }
    package com.itheima.service.impl;
    
    import com.itheima.dao.IAccountDao;
    import com.itheima.dao.impl.AccountDaoImpl;
    import com.itheima.factory.BeanFactory;
    import com.itheima.service.IAccountService;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl implements IAccountService {
        //    private IAccountDao accountDao = new AccountDaoImpl() ;
        private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");
    
        public void saveAccount() {
            accountDao.saveAccout();
        }
    }

    第二步:利用反射,创建一个工厂

    #bean.properties
    accountService = com.itheima.service.impl.AccountServiceImpl accountDao = com.itheima.dao.impl.AccountDaoImpl
    package com.itheima.factory;
    
    import java.io.InputStream;
    import java.util.Properties;
    
    /**
     * 创建Bean对象的工厂
     * bean:在计算机英语中,有可重用组件的意思。
     * javaBean:用java语言编写的可重用组件。
     * 它就是创建文明的service和dao对象的。
     * <p>
     * 第一个:需要一个配置文件,配置service和dao
     * 配置内容:唯一标志 = 全限定类名
     * 第二个:通过读取配置文件中配置的内容,反射创建对象。
     * <p>
     * 我们的配置文件可以使xml和properties
     */
    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);
                bean = Class.forName(beanPath).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bean;
        }
    
    }

    第三步:模拟一个表现层,用于调用业务层

    package com.itheima.ui;
    
    import com.itheima.factory.BeanFactory;
    import com.itheima.service.IAccountService;
    import com.itheima.service.impl.AccountServiceImpl;
    
    /**
     * 模拟一个表现层,用于调用业务层
     */
    public class Client {
        public static void main(String[] args){
    //        AccountServiceImpl as = new AccountServiceImpl();
            AccountServiceImpl as = (AccountServiceImpl) BeanFactory.getBean("accountService");
            as.saveAccount();
        } 
    }

    以上创建的为多例模式,如果想改成单例模式怎么办呢?

    package com.itheima.factory;
    
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    /**
     * 创建Bean对象的工厂
     * bean:在计算机英语中,有可重用组件的意思。
     * javaBean:用java语言编写的可重用组件。
     * 它就是创建文明的service和dao对象的。
     * <p>
     * 第一个:需要一个配置文件,配置service和dao
     * 配置内容:唯一标志 = 全限定类名
     * 第二个:通过读取配置文件中配置的内容,反射创建对象。
     * <p>
     * 我们的配置文件可以使xml和properties
     */
    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);
                // 实例化容器
                beans = new HashMap<String, Object>();
                // 取出配置文件中所有的key
                Enumeration<Object> 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的名称获取bean对象
         */
       /* public static Object getBean(String beanName) {
            Object bean = null;
    
            try {
                String beanPath = props.getProperty(beanName);
                bean = Class.forName(beanPath).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bean;
        }*/
        // 根据bean的名称获取对象
        public static Object getBean(String beanName) {
            return beans.get(beanName);
        }
    
    }
    package com.itheima.ui;
    
    import com.itheima.factory.BeanFactory;
    import com.itheima.service.IAccountService;
    import com.itheima.service.impl.AccountServiceImpl;
    
    /**
     * 模拟一个表现层,用于调用业务层
     */
    public class Client {
        public static void main(String[] args){
    //        AccountServiceImpl as = new AccountServiceImpl();
            AccountServiceImpl as = (AccountServiceImpl) BeanFactory.getBean("accountService");
            for (int i = 0; i < 5; i++) {
                System.out.println(as);
            }
            as.saveAccount();
        } 
    }

    5.IOC的概念

    6.使用spring的IOC解决程序间的耦合问题

    6.1准备 spring的开发包

    6.2创建业务层接口和实现类

    package com.itheima.service;
    
    /**
     * 账户业务层的接口
     */
    public interface IAccountService {
    
        /**
         * 模拟保存账户
         */
        void saveAccount();
    }
    package com.itheima.service.impl;
    
    import com.itheima.dao.IAccountDao;
    import com.itheima.dao.impl.AccountDaoImpl;
    import com.itheima.service.IAccountService;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl implements IAccountService {
    
        private IAccountDao accountDao = new AccountDaoImpl(); //此处有依赖关系待解决
    
        public void  saveAccount(){
            accountDao.saveAccount();
        }
    }

    6.3创建持久层接口和实现类

    package com.itheima.dao;
    
    /**
     * 账户的持久层接口
     */
    public interface IAccountDao {
    
        /**
         * 模拟保存账户
         */
        void saveAccount();
    }
    package com.itheima.dao.impl;
    
    import com.itheima.dao.IAccountDao;
    
    /**
     * 账户的持久层实现类
     */
    public class AccountDaoImpl implements IAccountDao {
    
        public  void saveAccount(){
    
            System.out.println("保存了账户");
        }
    }

    6.4引入spring的jar包

    <?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>day01_eesy_03spring</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
        </dependencies>
    
    </project>

    6.5创建spring可以读取的配置文件bean.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>

    <!-- bean 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中
    id 属性:对象的唯一标识。
    class 属性:指定要创建对象的全限定类名

    6.6测试

    package com.itheima.ui;
    
    import com.itheima.dao.IAccountDao;
    import com.itheima.service.IAccountService;
    import com.itheima.service.impl.AccountServiceImpl;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * 模拟一个表现层,用于调用业务层
     */
    public class Client {
        /**
         * 获取spring的ioc核心容器,并根据id获取对象
         *
         * @param args
         */
        public static void main(String[] args) {
            //1.获取核心容器对象
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
            //2.根据id获取bean对象
            IAccountService as = (IAccountService) ac.getBean("accountService");
            IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);
            System.out.println(as);
            System.out.println(adao);
        }
    }

    7.spring基于XML配置的IOC细节

    7.1spring中工厂的类结构图

    7.2BeanFactory和ApplicationContext的区别

    BeanFactory 才是 Spring 容器中的顶层接口。
    ApplicationContext 是它的子接口。
    BeanFactory 和 ApplicationContext 的区别:
      创建对象的时间点不一样。
      ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
      BeanFactory:什么使用什么时候创建对象。

    7.3ApplicationContext 接口的实现类

    ClassPathXmlApplicationContext:
      它是从类的根路径下加载配置文件 推荐使用这种
    FileSystemXmlApplicationContext:
      它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
    AnnotationConfigApplicationContext:
      当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。

    7.4实例化Bean的三种方式

     <!-- 第一种方式:使用默认构造函数创建。
                在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
                采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。    -->
            <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
    package com.itheima.factory;
    
    import com.itheima.service.IAccountService;
    import com.itheima.service.impl.AccountServiceImpl;
    
    /**
     * 模拟一个工厂,该类可能存在jar包中,我们无法通过修改源码的方式来提供默认构造函数
     */
    public class InstanceFactory {
    
        public IAccountService getAccountService() {
            return new AccountServiceImpl();
        }
    }
    
    <!--第二种方式: 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象,并存入spring容器)    -->
            <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
            <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>

    factory-bean 属性:用于指定实例工厂bean的id。
    factory-method 属性:用于指定实例工厂中创建对象的方法。

    package com.itheima.factory;
    
    import com.itheima.service.IAccountService;
    import com.itheima.service.impl.AccountServiceImpl;
    
    /**
     * 模拟一个工厂,该类可能存在jar包中,我们无法通过修改源码的方式来提供默认构造函数
     */
    public class StaticFactory {
    
        public static IAccountService getAccountService() {
            return new AccountServiceImpl();
        }
    }
     <!--第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象,并存入spring容器)-->
        <bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>

    id属性:指定 bean的id,用于从容器中获取
    class属性:指定静态工厂的全限定类名
    factory-method属性:指定生产对象的静态方法

    7.5bean标签

    7.6bean的作用范围和生命周期

    8.spring的依赖注入

    8.1依赖注入的概念

    8.2构造函数注入

    顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置的方式,让 spring 框架来为我们注入。具体代码如下:

    package com.itheima.service.impl;
    
    import com.itheima.service.IAccountService;
    
    import java.util.Date;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl implements IAccountService {
    
        //如果是经常变化的数据,并不适用于注入的方式
        private String name;
        private Integer age;
        private Date birthday;
    
        public AccountServiceImpl(String name,Integer age,Date birthday){
            this.name = name;
            this.age = age;
            this.birthday = birthday;
        }
    
        public void  saveAccount(){
            System.out.println("service中的saveAccount方法执行了。。。"+name+","+age+","+birthday);
        }
    
    }
    <?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中的依赖注入
            依赖注入:
                Dependency Injection
            IOC的作用:
                降低程序间的耦合(依赖关系)
            依赖关系的管理:
                以后都交给spring来维护
            当前类需要用到其他类的对象,由spring来为我们维护,我们只需要在配置文件中说明
            依赖关系的维护就称之为依赖注入。
            依赖注入:
                能注入的数据有三类:
                    1.基本类型和String
                    2.其他基本bean类型(在配置文件或者注解配置过的bean)
                    3.复杂类型/集合类型
                注入的方式有三种:
                    1.使用构造函数提供
                    2.使用set方法踢狗
                    3.使用注解提供
        -->
    
        <!--构造函数注入
            使用的标签:constructor-arg
            标签出现的位置:bean标签的内部
            标签中的属性
                type:用于指定要注入数据的数据类型,该数据类型也是构造函数中每个或者某些参数的类型
                index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
                name:用于指定给构造函数中指定名称的参数赋值(更常用)
                =============以上三个用于指定给构造函数中哪个参数赋值===============================
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
        -->
        <!--
         优势:
            在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
         弊端:
            改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
        -->
        <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
            <constructor-arg name="name" value="test"></constructor-arg>
            <constructor-arg name="age" value="18"></constructor-arg>
            <constructor-arg name="birthday" ref="now"></constructor-arg>
        </bean>
        <!-- 配置一个日期对象 -->
        <bean id="now" class="java.util.Date"></bean>
    
    
    </beans>

    8.2set方法注入

    package com.itheima.service.impl;
    
    import com.itheima.service.IAccountService;
    
    import java.util.Date;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl2 implements IAccountService {
    
        //如果是经常变化的数据,并不适用于注入的方式
        private String name;
        private Integer age;
        private Date birthday;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public void  saveAccount(){
            System.out.println("service中的saveAccount方法执行了。。。"+name+","+age+","+birthday);
        }
    
    }
    <?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">
        <!-- 配置一个日期对象 -->
        <bean id="now" class="java.util.Date"></bean>
    
    
        <!-- set方法注入                更常用的方式
            涉及的标签:property
            出现的位置:bean标签的内部
            标签的属性
                name:用于指定注入时所调用的set方法名称
                value:用于提供基本类型和String类型的数据
                ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
            优势:
                创建对象时没有明确的限制,可以直接使用默认构造函数
            弊端:
                如果有某个成员必须有值,则获取对象是有可能set方法没有执行。
        -->
        <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2">
            <property name="name" value="TEST" ></property>
            <property name="age" value="21"></property>
            <property name="birthday" ref="now"></property> //注释掉这个成员照样可以执行
        </bean>
    
    
    </beans>

    8.3注入集合属性

    package com.itheima.service.impl;
    
    import com.itheima.service.IAccountService;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Properties;
    import java.util.Set;
    import java.util.Map;
    
    /**
     * 账户的业务层实现类
     */
    public class AccountServiceImpl3 implements IAccountService {
    
        private String[] myStrs;
        private List<String> myList;
        private Set<String> mySet;
        private Map<String,String> myMap;
        private Properties myProps;
    
        public void setMyStrs(String[] myStrs) {
            this.myStrs = myStrs;
        }
    
        public void setMyList(List<String> myList) {
            this.myList = myList;
        }
    
        public void setMySet(Set<String> mySet) {
            this.mySet = mySet;
        }
    
        public void setMyMap(Map<String, String> myMap) {
            this.myMap = myMap;
        }
    
        public void setMyProps(Properties myProps) {
            this.myProps = myProps;
        }
    
        public void  saveAccount(){
            System.out.println(Arrays.toString(myStrs));
            System.out.println(myList);
            System.out.println(mySet);
            System.out.println(myMap);
            System.out.println(myProps);
        }
    
    
    }
    <?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">
    
        <!-- 复杂类型的注入/集合类型的注入
            用于给List结构集合注入的标签:
                list array set
            用于个Map结构集合注入的标签:
                map  props
            结构相同,标签可以互换
        -->
        <bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl3">
            <property name="myStrs">
                <set>
                    <value>AAA</value>
                    <value>BBB</value>
                    <value>CCC</value>
                </set>
            </property>
    
            <property name="myList">
                <array>
                    <value>AAA</value>
                    <value>BBB</value>
                    <value>CCC</value>
                </array>
            </property>
    
            <property name="mySet">
                <list>
                    <value>AAA</value>
                    <value>BBB</value>
                    <value>CCC</value>
                </list>
            </property>
    
            <property name="myMap">
                <props>
                    <prop key="testC">ccc</prop>
                    <prop key="testD">ddd</prop>
                </props>
            </property>
    
            <property name="myProps">
                <map>
                    <entry key="testA" value="aaa"></entry>
                    <entry key="testB">
                        <value>BBB</value>
                    </entry>
                </map>
            </property>
        </bean>
    
    </beans>
    package com.itheima.ui;
    
    import com.itheima.service.IAccountService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * 模拟一个表现层,用于调用业务层
     */
    public class Client {
    
        /**
         *
         * @param args
         */
        public static void main(String[] args) {
            //1.获取核心容器对象
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    //        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
            //2.根据id获取Bean对象
    //        IAccountService as  = (IAccountService)ac.getBean("accountService");
    //        as.saveAccount();
    //        IAccountService as  = (IAccountService)ac.getBean("accountService2");
    //        as.saveAccount();
            IAccountService as  = (IAccountService)ac.getBean("accountService3");
            as.saveAccount();
        }
    }
  • 相关阅读:
    const char* && string && String^ 类型转换
    vs2010 vc++ 统一修改所有工程的目录配置
    OSG开发概览
    osg渲染数据高程文件
    postgis数据库文件shapefile导入 dbf file (.dbf) can not be opened.shapefile import failed.
    Point ZM 转换为Point 类型
    Extjs关于alert显示不出—异步问题
    js执行顺序<转>
    HTML中IFrame父窗口与子窗口相互操作
    SpringMVC学习系列(6) 之 数据验证
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/11511863.html
Copyright © 2011-2022 走看看