cyAspNet 2019-07-01
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
方便解耦,简化开发
AOP变成的支持
声明式事务的支持
方便程序的测试
方便集成各种优秀框架
降低JavaEE API的使用难度
Java源码是经典学习范例
Spring框架是一个分层架构,它包含一系列的功能要素并被分为大约20个模块。这些模块分为Core Container、DataAccess/Integration、Web、AOP、Instrumentation和测试部分。如下图所示:


程序的耦合
/**
 * 客户的业务层实现类
 */
public class CustomerServiceImpl implements ICustomerService {
    
    private ICustomerDao customerDao = new CustomerDaoImpl();    
}public class JdbcDemo1 {
    
    /**
     * JDBC操作数据库的基本入门中存在什么问题?
     *       导致驱动注册两次是个问题,但不是严重的。
     *       严重的问题:是当前类和mysql的驱动类有很强的依赖关系。
     *                  当我们没有驱动类的时候,连编译都不让。
     * 那这种依赖关系,就叫做程序的耦合
     * 
     * 我们在开发中,理想的状态应该是:
     *       我们应该尽力达到的:编译时不依赖,运行时才依赖。
     *      
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取连接
        //3.获取预处理sql语句对象
        //4.获取结果集
        //5.遍历结果集
    }解决程序耦合的思路
在JDBC种是通过反射来注册驱动的,代码如下:
Clas.forName("com.mysql.jdbc.Driver");工厂模式解耦
控制反转---Inversion Of Control
上面解耦的思路有两个问题


以及进行Inversion of Control(IoC) / Dependency Injection(DI)操作相关的所有类。
如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等。
准备项目需要得jar包
在src路径下创建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-framework-4.2.4.RELEASE\docs\spring-framework-reference\html\xsd-configuration.html
        文档末尾 -->
    <!-- 
        1. 基本配置:
            bean标签:指定要创建的实体类
            id属性:可以为任意值 但是在整个配置文件中唯一
            class属性:要实例化类的全限定名 反射
     -->
    <bean id="user" class="com.itzhouq.domain.User"></bean>
</beans>测试
package com.itzhouq.domain;
public class User {
    public void run() {
        System.out.println("run");
    }
}package com.itzhouq.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itzhouq.domain.User;
public class UserTeset {
    
    @Test
    public void test() {//自己new的对象
        User user = new User();
        user.run();
    }
    
    @Test
    public void test2() {//spring的ioc创建对象
        //加载配置文件  src/classes类路径
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //找Spring要对象
        User user = (User) context.getBean("user");
        user.run();
    }
}作用
属性
<bean id="user" class="cn.itzhouq.domain.User" scope="singleton" ></bean>
prototype: 多实例
什么时候用默认值singleton(单实例)? 什么时候用prototype(多实例)?
单例对象:scope="singleton"
生命周期:
生命周期:
无参构造方式(最常用)
@Test//测试bean的三种创建方式------无参构造方式
    public void test3() {
        //加载配置文件  src/classes类路径
        ApplicationContext context = new         ClassPathXmlApplicationContext("applicationContext.xml");
        //找Spring要对象
        User user = (User) context.getBean("user");
        user.run();
    }静态工厂方式(了解)
条件:需要有一个工厂类,在这个工厂类中还需要一个静态方法
package com.itzhouq.utils;
import com.itzhouq.domain.User;
public class BeanFactory {
    
    public static User createUser() {
        return new User();
    }
}<!-- 静态工厂方式 -->
    <bean id="user" class="com.itzhouq.utils.BeanFactory" factory-method ="createUser">测试
@Test//测试bean的三种创建方式------静态工厂方式
    public void test4() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = (User) context.getBean("user");
        System.out.println(user1);//com.itzhouq.domain.User@5f3a4b84
        User user2 = (User) context.getBean("user");
        System.out.println(user2);//com.itzhouq.domain.User@5f3a4b84
    }实例工厂方式(了解)
package com.itzhouq.utils;
import com.itzhouq.domain.User;
public class BeanFactory {
    
//    public static User createUser() {
//        return new User();
//    }
    
    //普通方法----实例工厂
    public User createUser() {
        return new User();
    }
}配置文件
<!-- 实例工厂 --> <bean id="beanFactory" class="com.itzhouq.utils.BeanFactory"></bean> <bean id="user" factory-bean="beanFactory" factory-method="createUser"></bean>
测试
@Test//测试bean的三种创建方式------实例工厂方式
    public void test5() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user1 = (User) context.getBean("user");
        System.out.println(user1);//com.itzhouq.domain.User@5f3a4b84
        User user2 = (User) context.getBean("user");
        System.out.println(user2);//com.itzhouq.domain.User@5f3a4b84
    }public class Lession01 {
    @Test
    public void test01(){
        //Spring容器加载有3种方式
        //第一种:ClassPathXmlApplicationContext    ClassPath类路径加载:指的就是classes路径
        //最常用,Spring的配置文件以后就放在src路径下
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //第二种方式:文件系统路径获得配置文件【绝对路径】
        ApplicationContext context = new FileSystemXmlApplicationContext("E:\\workspaces\\IdeaProject\\Spring-day02-gyf\\src\\beans.xml");
        IUserService user = (IUserService) context.getBean("userService");
        user.add();
        //第三种方式:
        String path = "E:\\workspaces\\IdeaProject\\Spring-day02-gyf\\src\\beans.xml";
        BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
        IUserService user1 = (IUserService) factory.getBean("userService");
        user1.add();
    }
}Spring内部创建对象的原理
1. 解析xml文件,获得类名,id,属性 2. 通过反射,用类型创建对象 3. 给创建的对象赋值
ApplicationContext是对BeanFactory扩展,提供了更多功能
入门举例:
创建一个接口Car
package com.itzhouq.service;
public interface Car {
    public void run();
}创建实现类CarImpl
package com.itzhouq.serviceImpl;
import com.itzhouq.service.Car;
public class CarImpl implements Car {
    private String name;
    
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println(name+"车跑起来了.....");
    }
}测试
package com.itzhouq.test;
import org.junit.Test;
import com.itzhouq.serviceImpl.CarImpl;
public class CarTest {    
    @Test//自己new对象 自己属性赋值的方式
    public void test() {
        CarImpl car = new CarImpl();
        car.setName("qq");
        car.run();//qq车跑起来了.....
    }
}入门举例2:依赖注入的方式
配置文件:
<!-- DI:属性的依赖注入 -->
   <bean id="car" class="com.itzhouq.serviceImpl.CarImpl">
           <!-- 
               property:是set属性的方式
               name:要赋值的属性名
               value:要赋的值
            -->
            <property name="name" value="兰博基尼"></property>
   </bean>测试
@Test   //Spring的IOC
    public void test2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Car car = (Car)context.getBean("car");
        //把这个对象的属性也在创建的时候给顺便赋值了-----DI
        car.run();//兰博基尼车跑起来了.....
    }依赖注入的方式
给CarImpl设置有参构造
package com.itzhouq.serviceImpl;
import com.itzhouq.service.Car;
public class CarImpl implements Car {
    private String name;
    private double price;
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public CarImpl() {}
    //有参的构造方法----DI的构造器注入方式
    public CarImpl(String name, double price) {
        super();
        this.name = name;
        this.price = price;
    }
    @Override
    public void run() {
        System.out.println("价值"+price+"的"+name+"车跑起来了.....");
    }
}配置文件
<!-- DI的注入方式,构造器注入方式 
           name:要赋值的属性名
           value:要赋的值(针对的是基本数据类型和String类型)
           ref针对的是对象类型
   -->
   <bean id="car" class="com.itzhouq.serviceImpl.CarImpl">
           <constructor-arg name="name" value="BMW"></constructor-arg>
           <constructor-arg name="price" value="1000000"></constructor-arg>
   </bean>测试
@Test   //Spring的DI注入方式----构造器的注入方式(了解)
    public void test3() {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Car car = (Car)context.getBean("car");
        car.run();//价值1000000.0的BMW车跑起来了.....
    }写一个Person接口
package com.itzhouq.service;
public interface Person {
}PersonImpl实现接口Person,设置set方法
package com.itzhouq.serviceImpl;
import com.itzhouq.service.Car;
import com.itzhouq.service.Person;
public class PersonImpl implements Person {
    private String name;
    private Car car;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    @Override
    public String toString() {
        return "PersonImpl [name=" + name + ", car=" + car + "]";
    }
}配置文件
<bean id="car" class="com.itzhouq.serviceImpl.CarImpl">
           <constructor-arg name="name" value="BMW"></constructor-arg>
           <constructor-arg name="price" value="1000000"></constructor-arg>
   </bean>
   
   <!-- DI的注入方式,set注入方式 
           name:要赋值的属性名
           value:要赋的值(针对的是基本数据类型和String类型)
           ref针对的是对象类型,指的是Spring中bean的id名
   -->
   <bean id="person" class="com.itzhouq.serviceImpl.PersonImpl">
           <property name="name" value="jack"></property>
           <property name="car" ref="car"></property>
   </bean>测试
@Test   //Spring的DI注入方式----set的注入方式(了解)
    public void test4() {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Person person = (Person) context.getBean("person");
        System.out.println(person);
        //PersonImpl [name=jack, car=CarImpl [name=BMW, price=1000000.0]]
    }配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p"
         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="customerService" 
          class="com.itheima.service.impl.CustomerServiceImpl4"
          p:name="test" p:age="21" p:birthday-ref="now"/>
</beans>创建一个类CollBean,设置set方法
package com.itzhouq.domain;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CollBean {
    private String[] ss;
    private List ll;
    private Map mm;
    private Properties properties;
    public String[] getSs() {
        return ss;
    }
    public void setSs(String[] ss) {
        this.ss = ss;
    }
    public List getLl() {
        return ll;
    }
    public void setLl(List ll) {
        this.ll = ll;
    }
    public Map getMm() {
        return mm;
    }
    public void setMm(Map mm) {
        this.mm = mm;
    }
    public Properties getProperties() {
        return properties;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    @Override
    public String toString() {
        return "CollBean [ss=" + Arrays.toString(ss) + ", ll=" + ll + ", mm=" + mm + ", properties=" + properties + "]";
    }
}配置文件
<bean id="car" class="com.itzhouq.serviceImpl.CarImpl">
           <constructor-arg name="name" value="BMW"></constructor-arg>
           <constructor-arg name="price" value="1000000"></constructor-arg>
   </bean>
   <!-- DI复杂属性注入 -->
   <bean id="collBean" class="com.itzhouq.domain.CollBean">
           <property name="ss">
               <!-- 数组类型 -->
               <list>
                   <value>aaa</value>
                   <value>bbb</value>
                   <value>ccc</value>
               </list>
           </property>
           <property name="ll">
               <!-- 集合类型 -->
               <list>
                   <value>111</value>
                   <value>222</value>
                   <ref bean="car"></ref>
               </list>
           </property>
           <property name="mm">
               <!-- map类型 -->
               <map>
                   <entry key="k1" value="AAA"></entry>
                   <entry key="k2" value="BBB"></entry>
                   <entry key="k3" value-ref="car"></entry>
               </map>
           </property>
           <property name="properties">
               <!-- properties -->
               <props>
                   <prop key="hibernate.username">root</prop>
                   <prop key="hibernate.password">1234</prop>
               </props>
           </property>
   </bean>package com.itzhouq.test;
      
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      import com.itzhouq.domain.CollBean;
      
      public class CollBeanTest {
          @Test
          public void test() {
              ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
              CollBean cb = (CollBean) context.getBean("collBean");
              System.out.println(cb);
              /*
               * CollBean [ss=[aaa, bbb, ccc], 
               * ll=[111, 222, CarImpl [name=BMW, price=1000000.0]],
               *  mm={k1=AAA, k2=BBB, k3=CarImpl [name=BMW, price=1000000.0]}, 
               *  properties={hibernate.password=1234, hibernate.username=root}]
               */
          }
      }
创建dao层和dao实现层
package com.itzhouq.dao;
public interface UserDao {
    void save();
}package com.itzhouq.daoImpl;
import com.itzhouq.dao.UserDao;
public class UserDaoImpl implements UserDao{
    @Override
    public void save() {
        System.out.println("操作数据库,保存用户的数据");    
    }
}创建Service层和实现层
package com.itzhouq.service;
public interface UserService {
    public void save();
}package com.itzhouq.serviceImpl;
import com.itzhouq.dao.UserDao;
import com.itzhouq.daoImpl.UserDaoImpl;
import com.itzhouq.service.UserService;
public class UserServiceImpl implements UserService {
    private String name;
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public void save() {
        System.out.println(name);
        //调用dao
        userDao.save();
    }
}配置文件
<?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">
    <!-- 创建dao -->
    <bean id="userDao" class="com.itzhouq.daoImpl.UserDaoImpl"></bean>
    
    <!-- 创建service -->
    <bean id="UserService" class="com.itzhouq.serviceImpl.UserServiceImpl">
        <property name="name" value="要开始访问dao了"></property>
        <property name="userDao" ref="userDao"></property>
    </bean>
</beans>测试
@Test    //使用Spring的IOC+DI来实现对象的创建和赋值
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("UserService");
        userService.save();
        //要开始访问dao了
        //操作数据库,保存用户的数据
    }