框架spring

一、概述

  3.1  Spring是轻量级的开源JavaEE框架

  3.2  Spring可以解决企业应用开发的复杂性

  3.3  Spring有两个核心部分:IOC 和 AOP

    (1)IOC:控制反转,把创建对象过程交给Spring管理

    (2)AOP:面向切面,不修改源代码进行功能增强

  3.4 Spring特点:

    (1)方便解耦,简化开发

    (2)Aop编程支持

    (3)方便程序测试

    (4)方便和其它框架进行整合

    (5)方便进行事务操作

    (6)降低API开发难度

二、入门案例

  2.1 Spring下载

    下载地址:repo.spring.io

   2.2 创建普通java工程

  2.3 导入jar包

   Spring需要的基础核心包包括如下四个(还要加上commons-logging包 这个包不是Spring的包但是Spring需要依赖到这个包)

 

    因为创建的是普通java项目所以需要在目录下创建一个lib文件夹,并把上述包导入到lib下

  2.4 创建普通类 在类中创建普通方法

  

 

 

   2.5 创建Spring配置文件,在配置文件中配置创建的对象

  

 

 

   2.6 测试代码的编写

  

 

 

   

public class Spring5Test {

    @Test
    public void testAdd(){
        // 1.加载Spring配置文件
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

        // 2. 获取对象
        User user = classPathXmlApplicationContext.getBean("user",User.class);

        // 3. 测试
        user.add();
    }
}

三、IOC

 3.1  IOC基本概念和原理

   1、什么是IOC:

     (1)控制反转:把对象创建和对象之间的调用过程,交给Spring管理

        (2)使用IOC目的:降低耦合度

     (3)入门案例即为IOC实现

   2、IOC底层原理

    3.2.1 xml解析、工厂模式、反射

    

 

 

 

 

 

   

 

 

     3.2.2 IOC接口

    1. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
    2. Spring提供IOC容器两种实现方式:(两个接口)
      1. BeanFactory: IOC容器的基本实现接口,是Spring内部的使用接口,一般不提供给开发人员进行使用
        特点:加载配置文件时不会创建对象,在获取(使用)对象时才去创建
      2. ApplicationContext: BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用(因为把对象的创建放在项目启动过程会更好)
        特点:在加载配置文件时就会把配置文件的对象进行创建
    3. ApplicationContext的实现类:
      1. FileSystemXmlApplicationContext : 路径需要用硬盘中的全路径
        ApplicationContext  fileSystemXmlApplicationContext = new FileSystemXmlApplicationContext("D:\\study\\Spring\\Spring5_JavaProjectTest\\src\\spring_bean1.xml");
      2. ClassPathXmlApplicationContext:路径用src资源下的类路径即可 
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");  

3.2 IOC Bean管理

    3.2.1 什么是Bean管理?

        Bean管理指两个操作: 1)Spring创建对象 2)Spring注入属性

        Bean管理的两种方式:1)基于xml配置文件方式实现  2)基于注解方式实现

    3.2.2 基于xml方式的Bean管理

      1、基于XML方式创建对象

        <bean id="user" class="com.lili.spring.User"></bean>

       (1)在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建

        (2)bean标签中的常用属性:

          id: 唯一标识

          class:类全路径

        (3)创建对象时默认使用对象类的无参构造创建

      2、基于XML方式注入属性

        (1)DI:依赖注入,就是注入属性。

        (2)注入属性方式一:用set注入

public class Book {
    private String bname;
    public void setBname(String bname){
        this.bname = bname;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bname='" + bname + '\'' +
                '}';
    }
}


<?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="user" class="com.lili.spring.User"></bean>

    <bean id="book" class="com.lili.spring.pojo.Book">
        <property name="bname" value="易经"></property>
     </bean>
</beans>



 public void testBookDI(){
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

        Book book = classPathXmlApplicationContext.getBean("book", Book.class);

        book.toString();
    }

 

            (3)第二种注入方式:使用有参数构造进行注入

public class Orders {
    private String oname;
    private String address;

    public Orders(String oname, String address) {
        this.oname = oname;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "oname='" + oname + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}



    <bean id="orders" class="com.lili.spring.pojo.Orders">
        <constructor-arg name="oname"  value="lili"></constructor-arg>
        <constructor-arg name="address" value="china"></constructor-arg>
    </bean>


   @Test
    public void testOrdersConstructorDI(){
        ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

        Orders orders = classPathXmlApplicationContext.getBean("orders", Orders.class);

        System.out.println(orders.toString());
    }

      (4) p名称空间注入: 简化xml注入方式  只做了解(使用不多)

        a) 添加一行xml约束 

        

 

 

         b)进行属性注入

          <bean id="pbook" class="com.lili.spring.pojo.Book" p:bname="lili"></bean>

 

      (5)其它类型的属性注入
        a)字面量
          null值:
<!-- 属性注入为空值 -->
<bean id="nullBookName" class="com.lili.spring.pojo.Book">
<property name="bname">
<null/>
</property>
</bean>
          属性值包含特殊符号:
<!-- 属性值中有特殊符号 -->
<bean id="specBookName" class="com.lili.spring.pojo.Book">
<property name="bname">
<value><![CDATA[<<南京>>]]></value>
</property>
</bean>
        b)注入属性-外部bean
          创建两个类 service类和dao类
          在service类中调用dao类的方法
          在配置文件中进行配置
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("dao update");
}
}

public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public void add(){
System.out.println("service....");
userDao.update();
}
}

<!-- 外部bean注入 -->
<bean id="userDaoImpl" class="com.lili.spring.dao.UserDaoImpl"></bean>
<bean id="userService" class="com.lili.spring.service.UserService">
<property name="userDao" ref="userDaoImpl"></property>
</bean>


@Test
public void testUserService(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

UserService userService = classPathXmlApplicationContext.getBean("userService", UserService.class);

userService.add();
}
          c) 注入属性-内部bean
            一对多关系:部门和员工
            
public class Dept {
private String dname;

public void setDname(String dname) {
this.dname = dname;
}

@Override
public String toString() {
return "Dept{" +
"dname='" + dname + '\'' +
'}';
}
}

public class Emp {
private String ename;
private String gender;
private Dept dept;

public void setDept(Dept dept) {
this.dept = dept;
}

public void setEname(String ename) {
this.ename = ename;
}

public void setGender(String gender) {
this.gender = gender;
}


@Override
public String toString() {
return "Emp{" +
"ename='" + ename + '\'' +
", gender='" + gender + '\'' +
", dept=" + dept.toString() +
'}';
}
}


<!-- 内部bean与级联赋值 -->
<bean id="emp" class="com.lili.spring.pojo.Emp">
<property name="ename" value="lili"></property>
<property name="gender" value="woman"></property>
<property name="dept">
<bean id="dept" class="com.lili.spring.pojo.Dept">
<property name="dname" value="安保部"></property>
</bean>
</property>
</bean>

@Test
public void testInnerDi(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

Emp emp = classPathXmlApplicationContext.getBean("emp", Emp.class);

System.out.println(emp.toString());
}

          d) 注入属性--级联属性
public class Dept {
private String dname;

public void setDname(String dname) {
this.dname = dname;
}

@Override
public String toString() {
return "Dept{" +
"dname='" + dname + '\'' +
'}';
}
}


public class Emp {
private String ename;
private String gender;
private Dept dept;


public void setDept(Dept dept) {
this.dept = dept;
}

public Dept getDept() {
return dept;
}

public void setEname(String ename) {
this.ename = ename;
}

public void setGender(String gender) {
this.gender = gender;
}


@Override
public String toString() {
return "Emp{" +
"ename='" + ename + '\'' +
", gender='" + gender + '\'' +
", dept=" + dept.toString() +
'}';
}
}


<!-- 级联赋值 -->
<bean id="emp" class="com.lili.spring.pojo.Emp">
<property name="ename" value="lili"></property>
<property name="gender" value="woman"></property>
<property name="dept" ref="dept"></property>
<!-- 注意 这里需要emp bean类中需要提供getDept方法 -->
<property name="dept.dname" value="管理"></property>
</bean>

<bean id="dept" class="com.lili.spring.pojo.Dept">
<property name="dname" value="安保部"></property>
</bean>
          e) 注入属性--集合属性
public class ListStudent {
private String[] courses;
private List<String> list;
private Map<String,String> maps;
private Set<String> sets;

public void setCourses(String[] courses) {
this.courses = courses;
}

public void setList(List<String> list) {
this.list = list;
}

public void setMaps(Map<String, String> maps) {
this.maps = maps;
}

public void setSets(Set<String> sets) {
this.sets = sets;
}

@Override
public String toString() {
return "ListStudent{" +
"courses=" + Arrays.toString(courses) +
", list=" + list +
", maps=" + maps +
", sets=" + sets +
'}';
}
}

<!-- 集合注入 -->
<bean id="listStu" class="com.lili.spring.pojo.ListStudent">
<property name="courses">
<array>
<value>c</value>
<value>java</value>
</array>
</property>

<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>

<property name="maps">
<map>
<entry key="lili" value="lilivalue"></entry>
</map>
</property>

<property name="sets">
<set>
<value>setvalye1</value>
<value>set2value</value>
</set>
</property>
</bean>

@Test
public void testListDi(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

Object listStu = classPathXmlApplicationContext.getBean("listStu");

System.out.println(listStu.toString());
}
              在集合里面设置对象类型值
public class Course {
private String cname;

public void setCname(String cname) {
this.cname = cname;
}
}

public class ListStudent {
private String[] courses;
private List<String> list;
private Map<String,String> maps;
private Set<String> sets;

private List<Course> courseList;

public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}

public void setCourses(String[] courses) {
this.courses = courses;
}

public void setList(List<String> list) {
this.list = list;
}

public void setMaps(Map<String, String> maps) {
this.maps = maps;
}

public void setSets(Set<String> sets) {
this.sets = sets;
}

@Override
public String toString() {
return "ListStudent{" +
"courses=" + Arrays.toString(courses) +
", list=" + list +
", maps=" + maps +
", sets=" + sets +
'}';
}
}


<!-- 在集合里面设置对象类型值 -->
<bean id="listStu" class="com.lili.spring.pojo.ListStudent">
<property name="courses">
<array>
<value>c</value>
<value>java</value>
</array>
</property>

<property name="list">
<list>
<value>list1</value>
<value>list2</value>
</list>
</property>

<property name="maps">
<map>
<entry key="lili" value="lilivalue"></entry>
</map>
</property>

<property name="sets">
<set>
<value>setvalye1</value>
<value>set2value</value>
</set>
</property>

<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<bean id="course1" class="com.lili.spring.pojo.Course">
<property name="cname" value="c"></property>
</bean>
<bean id="course2" class="com.lili.spring.pojo.Course">
<property name="cname" value="java"></property>
</bean>
              把集合注入部分提取出来
                1)在Spring配置文件中引入名称空间util
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
>
2) 使用util标签完成list集合注入提取
public class Book {
private String bname;
private List<String> list;
public void setBname(String bname){
this.bname = bname;
}

public void setList(List<String> list) {
this.list = list;
}

@Override
public String toString() {
return "Book{" +
"bname='" + bname + '\'' +
'}';
}
}


<!-- 使用util标签完成list集合注入提取 -->
<util:list id="bookList">
<value>易经</value>
<value>九阳神功</value>
</util:list>
<bean id="bookList" class="com.lili.spring.pojo.Book">
<property name="list" ref="bookList"></property>
</bean>
      (6)IOC操作Bean管理(FactoryBean)
         Spring有两种bean类型,一种是普通bean另一种是工厂bean
          普通bean:在配置文件中定义的bean类型就是返回类型
          工厂bean:在配置文件定义bean类型可以和返回类型不一样。
            第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean
           第二步:实现接口里面的方法,在实现方法中定义返回的bean类型
public class FactoryBean implements org.springframework.beans.factory.FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("java");
return course;
}

@Override
public Class<?> getObjectType() {
return null;
}

@Override
public boolean isSingleton() {
return org.springframework.beans.factory.FactoryBean.super.isSingleton();
}
}

<!-- 实现接口里面的方法,在实现方法中定义返回的bean类型 -->
<bean id="factoryBean" class="com.lili.spring.pojo.factorybeans.FactoryBean"></bean>

@Test
public void factoryTest(){
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_bean1.xml");

Course course = classPathXmlApplicationContext.getBean("factoryBean", Course.class);
System.out.println(course.toString());
}
      (7)IOC操作Bean管理(bean作用域)
         设置单实例和多实例:默认是单实例
          
<bean id="user" class="com.lili.spring.pojo.User" scope="prototype"></bean>
            <bean id="user" class="com.lili.spring.pojo.User" scope="singleton"></bean>
           singleton和prototype区别:
              1) singleton创建单实例 prototype创建多实例
              2)singleton时,ClassPathXmlApplicationContext加载spring配置文件时就会创建对象实例
                prototype,ClassPathXmlApplicationContext加载spring配置文件时不会创建对象实例,在使用时创建
            request,session

      (8) IOC Bean生命周期
          没有配置后置处理器共五步:
           (1) 通过构造器创建bean对象(无参)
          (2)为bean属性设置值和其它bean引用(set方法)
          (3)调用bean的初始化方法(需要进行配置初始化方法)
          (4)bean可用
          (5)容器关闭时调用bean的销毁方法(需要配置销毁方法)
            <bean id="user" class="com.lili.spring.pojo.User" scope="singleton" init-method="initMethod" destroy-method="destoryMethod"></bean>
          配置后置处理器时共七步:
            (1) 通过构造器创建bean对象(无参)
           (2)为bean属性设置值和其它bean引用(set方法)
           (3) 把bean的实例传递给bean后置处理器方法 (postProcessBeforeInitialization方法)
           (4)调用bean的初始化方法(需要进行配置初始化方法)
         (5) 把bean的实例传递给bean后置处理器方法 (postProcessAfterInitialization方法)
           (6)bean可用
           (7)容器关闭时调用bean的销毁方法(需要配置销毁方法)
            
            演示:
              1)创建类 实现接口BeanPostProcessor,创建后置处理器
  

   3.IOC操作Bean管理(xml自动装配)

       3.1 什么是自动装配? 根据指定装配规则(属性名称或属性类型),Spring自动将匹配的属性值进行注入
        
public class Dept {
}

public class Emp {
private Dept dept;

public void setDept(Dept dept) {
this.dept = dept;
}
}

<!-- 实现自动装配
bean标签的autowire 配置自动装配
autowire属性:
byName:根据属性名称注入 注入值bean的id值和类属性名相同
byType:根据属性类型注入 但有两个相同类型的bean时报错 r如下 有dept1 dept2 emp1的autowire报错
-->
<bean id="emp1" class="com.lili.spring.autowire.Emp" autowire="byName"></bean>
<bean id="emp1" class="com.lili.spring.autowire.Emp" autowire="byType"></bean>
<bean id="dept1" class="com.lili.spring.autowire.Dept"></bean>
<bean id="dept2" class="com.lili.spring.autowire.Dept"></bean>

      4.IOC操作Bean管理(外部属性文件)

      4.1 引入druid的jar包

      4.2 直接配置

        

 

 

       4.3 创建properties文件

      

 

 

       4.4 修改配置文件

      

 

 

       

 

 

 

  3.2.3 基于注解方式的Bean管理

 

 

     1、基于注解方式创建对象:

      1)引入依赖

      

 

      2)开启注解扫描

        注意 要加上context约束

      

 

 

       3)添加注解

 

 

      2. 注解扫描配置

      

 

 

       

 

 

     3. 基于注解方式注入属性

       (1)@Autowired : 根据属性类型自动装配

        

       (2) @Qualifier  : 根据属性名称进行注入  (spring中提供的 建议)

        和@Autowired一起使用。

        

         (3) @Resource : 可以根据属性类型也可以根据属性名称进行注入  (javax中提供的 不建议使用)

        

        (4)@Value : 注入普通类型

  

 

     4. 纯注解开发

      4.1 创建配置类 替代xml配置文件

      

 

 

        4.2 编写测试类

      

 

 

 

四、AOP

  4.1 AOP概述

 

   

 

 

  AOP底层原理:

    1、AOP底层使用动态代理

     (1)有两种情况:

      第一种:有接口情况,使用JDK动态代理

      

      第二种:无接口情况,使用CGLIB动态代理

    

 

 

   AOP使用

    1、Proxy类(使用Proxy类里面的方法创建)

      

 

 

     2、编写JDK动态代理代码

     

 

 

     

 

 

 

 

 

 

    3、相关术语:

      连接点:

      切入点:真正被增强的方法

      通知/增强:实际增强的逻辑部分:

          前置通知/后置~/环绕~/异常~最终~

      切面:动作,把通知应用到切入点的过程

  AOP操作(准备)

    

 

 

     

 

 

     

 

 

     

 

 

 

  4.2 Aspect注解方式

  

 

 

   3、进行通知的配置

    1)添加配置aop context配置约束 开启注解扫描

    

 

    2) 创建User UserProxy类

3) 在增强类上添加@Aspect

 

4) 开启Aspect生成代理对象

     

 

   4、配置不同类型的通知

    

 

     

 

     

 

 

   5、测试

    

 

 

   6、相同切入点抽取

    

    

 

 

  4.3Aspect配置文件方式

    

 

 

 

 5、jdbcTemplate

    5.1 配置jdbcTemplate

    

 

     

 

     

 

     

 

   5.2 JdbcTemplate操作数据库

    创建数据库对应实体

    

 

     

 

 6. 事务

  6.1 事务操作

  

 

   

 

   

 

 

 

   

 

   

 

    5、解决方法 :使用事务

    

 

   6.2 事务操作

    

 

   6.3 注解实现-声明式事务

    

 

 

 

     

    

 

   6.3.1 声明式事务管理参数配置

    

 

     1、propagation:事务传播行为

      

      

 

       

     2、isolation:事务隔离级别

      (1)有三个读问题:脏读、不可重复读、幻读

      脏读:一个未提交事务读到另一个未提交事务的数据

      

 

       不可重复读:一个未提交事务读取到另一个提交事务修改数据

      

 

      幻读:一个未提交事务读取到另一个提交事务添加数据

      解决:设置事务的隔离级别

      

 

       

 

     3、timeout:超时时间

    (1)事务需要在一定时间内进行提交,如果不提交则进行回滚

    (2)默认值是-1,即不超时 。设置时间以秒为单位

    

    4、readOnly:是否只读

      

    5、rolllbackFor:回滚

      设置出现哪些异常进行事务回滚

    6、noRollbackFor:不回滚

       设置出现哪些异常不进行事务回滚

  6.4 XML实现-声明式事务

    6.4.1 配置事务管理器

      

 

     6.4.2 配置通知

      

 

     6.4.3 配置切面

    

 

   6.5 完全注解开发

    1、创建配置类

 

      

     

 

     

 

 7. Spring5新功能-整合日志框架

  7.1 Spring5框架新功能

    

 

     第二步:创建log4j2.xml配置文件

      

 

     

 

     

 

    4、支持函数式风格

     

 

     5、支持整合Junit5

    

    

 

     

 

     

 

     

 

posted @ 2021-11-02 22:52  微~粒  阅读(46)  评论(0)    收藏  举报