IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> spring5学习笔记 -> 正文阅读

[Java知识库]spring5学习笔记

1 Spring框架概述

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

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

3 Spring有两个核心部分:IOC和Aop

IOC :控制反转,创建对象过程交给Spring进行管理

Aop : 面向切面,不修改源代码进行功能增强

4 Spring特点

  1. 方便解耦,简化开发
  2. Aop编程支持
  3. 方便程序测试
  4. 方便和其他框架进行整合
  5. 方便进行事务操作
  6. 降低API开发难度

下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring/

2 IOC容器

1 IOC 底层原理

1 什么是IOC Inversion of Control

  1. 控制反转,把对象创建个对象之间的调用过程,交给Spring进行管理
  2. 使用IOC目的:为了耦合度的降低

2 IOC底层原理

  1. xml解析,工厂模式,反射

2 IOC接口(BeanFactory)

  1. ioc 思想基于IOC容器完成,IOC容器底层就是对象工厂

  2. Spring提供IOC容器实现两种方式:(两个接口)

    1. BeanFactory: IOC 容器基本实现,Spring内部的使用接口,不提供开发人员试用

      加载配置文件时不会创建对象,在获取(使用)对象时才会创建对象

    2. ApplicationContext: BeanFactory 接口的子接口,提供更多更强大的功能一般由开发者使用

      加载配置文件时就会创建对象

  3. ApplicationContext接口有实现类

在这里插入图片描述

3 IOC操作Bean管理(基于xml)

1 什么是Bean管理

Bean管理是指两个操作

  1. Spring创建对象
  2. Spring注入

2 Bean管理操作有两种方式

  1. 基于xml配置文件方式
  2. 基于注解方式实现

1 基于xml方式创建对象

<!--配置User对象创建-->
<bean id="user" class="com.spring.User"></bean>
  1. 在Spring配置文件中,使用bean标签,标签里面添加相对应属性,就可以实现对象创建
  2. 在bean标签有很多属性
    1. id属性:唯一表述
    2. class属性:类的路径(包类路径)
  3. 创建对象时默认也是执行无惨构造函数完成对象创建

2 基于xml方式注入属性

  1. DI:依赖注入,就是注入属性

    1. set方法注入

      创建类,定义属性和对应的set方法

      在Spring配置文件配置对象创建,配置属性注入

在这里插入图片描述

  1. 使用有参构造函数注入

    1. 创建类,定义属性,创建属性对应有参构造函数方法

    2. 在Spring文件中配置

在这里插入图片描述

  3. p名称空间注入(了解)

     1. ?	使用p名称空间注入,可以简化xml配置方式

在这里插入图片描述
在这里插入图片描述

3 xml注入其他类型属性

1 字面量

  1. null值
    在这里插入图片描述
  2. 特殊符号
    在这里插入图片描述

4 注入属性-外部bean

? 1 创建两个类service类和dao类

在这里插入图片描述

? 2 在service调用dao里面的方法

public class UserService {
    //创建UserDao类型属性,生成set方法
    private UserDao userDao;
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }
    public void add(){
        System.out.println("Service add.............");
        userDao.update();
    }
}

? 3 在Spring配置文件中进行配置
在这里插入图片描述

5 注入属性-内部bean

  1. 一对多关系:部门和员工
  2. 在实体类之间表示一对多关系
// 部门类
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;
    //生成dept的get方法
    public Dept getDept() {
        return 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;
    }
    public  void add(){
        System.out.println(ename+"::"+gender+"::"+dept);
    }
}

3.在Spring配置文件中进行配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jgH90wMc-1637331724192)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20211031132730834.png)]

6 注入属性——级联赋值

第一种
在这里插入图片描述

第二种

在这里插入图片描述
在这里插入图片描述

7 注入集合属性

? 1.注入数组类型属性

? 2.注入list集合类型属性

? 3.注入Map集合类型属性

public class Stu {
    //数组类型属性
    private String[] course;
    //list 集合类型属性
    private List<String> list;
    //map集合类型属性
    private Map<String,String> map;
    //set集合属性
    private Set<String> sets;

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

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

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setCourse(String[] course) {
        this.course = course;
    }

}
<!--1 集合类型属性注入-->
<bean id="stu" class="com.spring5.collectiontype.Stu">
    <!--数组类型属性注入-->
    <property name="course">
        <array>
            <value>Java</value>
            <value>C#</value>
        </array>
    </property>
    <!--list属性注入-->
    <property name="list">
        <list>
            <value>zhang san</value>
            <value>li si</value>
        </list>
    </property>
    <!--map 类型属性注入-->
    <property name="map">
        <map>
            <entry key="Java" value="java"></entry>
            <entry key="PHP" value="php"></entry>
        </map>
    </property>
    <property name="sets">
        <set>
            <value>MySQL</value>
            <value>Redis</value>
        </set>
    </property>
</bean>

? 4.在集合里面设置对象类型值

<!--注入list集合类型,值是对象-->
<property name="courseList">
    <list>
        <ref bean="course1"></ref>
        <ref bean="course2"></ref>
    </list>
</property>
<!--创建多个course对象-->
<bean id="course1" class="com.spring5.collectiontype.Course">
    <property name="cname" value="Spring5"></property>
</bean>
<bean id="course2" class="com.spring5.collectiontype.Course">
    <property name="cname" value="MyBatis"></property>
</bean>

? 5.把集合注入部分提取出来

  1. 在Spring配置文件中引入名称命名空间util

  2. <?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: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">
    
    </beans>
    
    <!--提取list集合类型属性注入-->
<util:list id="bookList">
    <value>java</value>
    <value>php</value>
    <value>c</value>
</util:list>
<!--使用-->
<bean id="book" class="com.spring5.collectiontype.Book">
    <property name="list" ref="bookList"></property>
</bean>

4 IOC操作Bean管理(FactoryBean)

  1. Spirng有两种类型的bean,一种是普通bean,另一种工厂bean(factorybean)

  2. 普通bean:在配置文件中定义bean类型就是返回类型

  3. 工厂bean:在配置文件中定义bean类型可以与返回类型不一样

    ? 创建类,让这个类作为工厂bean,实现接口factorybean

    ? 实现接口里面的方法,在实现的方法中定义返回的bean类型

    public class MyBean implements FactoryBean<Course> {
        /**
         * 定义返回bean对象
         * @return
         * @throws Exception
         */
        @Override
        public Course getObject() throws Exception {
            Course course = new Course();
            course.setCname("abc");
            return course;
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    
        @Override
        public boolean isSingleton() {
            return FactoryBean.super.isSingleton();
        }
    }
    
    @Test
    public void test3(){
        ApplicationContext context =new ClassPathXmlApplicationContext("bean3.xml");

        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);
    }
}

5 IOC操作Bean管理(Bean作用域)

  1. 在Spring里面,设置创建bean实例是单实例还是多实例

  2. 在Spring里面,默认情况下,bean是单实例对象

@Testpublic 
void testCollection2(){    
		ApplicationContext context =new ClassPathXmlApplicationContext("bean2.xml");    
		Book book = context.getBean("book", Book.class);    
		Book book1 = context.getBean("book", Book.class);    
		//book.test();    
		System.out.println(book);
		//com.spring5.collectiontype.Book@b2c9a9c    
		System.out.println(book1);//com.spring5.collectiontype.Book@b2c9a9c
}

3.如何设置是单实例还是多实例

  1. 在Spring配置文件bean标签里面有属性scope用于设置单实例还是多实例

  2. scope属性值

    第一个值默认值,singleton,表示是单实例对象

    第二个值prototype,表示是多实例对象

    <bean id="book" class="com.spring5.collectiontype.Book" scope="prototype">   
     	<property name="list" ref="bookList">
     	</property>
     </bean>
    
    @Testpublic
     void testCollection2(){   
      			ApplicationContext context =new ClassPathXmlApplicationContext("bean2.xml");    
      			Book book = context.getBean("book", Book.class);    
      			Book book1 = context.getBean("book", Book.class);    
      			//book.test();    
      			System.out.println(book);//com.spring5.collectiontype.Book@b2c9a9c    
      			System.out.println(book1);//com.spring5.collectiontype.Book@4c178a76
    

}


3. singleton和prototype区别

1. singleton是单实例,prototype是多实例
2. 设置scope值是sington时,加载Spring配置文件时候就会创建单实例对象
3. 设置scope值是prototype时,不是在加载Spring文件时候创建对象,在调用getBean方法时创建多实例对象

## 6 IOC操作Bean管理(bean生命周期)

1. 声明周期

1. 从对象的创建到对象的销毁过程

2. bean生命周期

1. 通过构造器创建bean实例(无惨构造)
2. 为bean的属性设置和其他bean引用(调用set方法)
3. 调用bean的初始化方法
4. bean可以使用了
5. 当容器关闭时候,调用bean的销毁的方法

3. 演示bean生命周期

```java
public class Orders {
    public Orders() {
        System.out.println("第一步,调用无参构造");
    }
    private String oname;
    public void setOname(String oname){
        this.oname=oname;
        System.out.println("第二步,调用set方法设置属性值");
    }

    //创建执行初始化的方法
    public void initMethod(){
        System.out.println("第三步,执行初始化方法");
    }
    //销毁的方法
    public void destroyMethod(){
        System.out.println("第五步,销毁");
    }
}
@Test
public void testBean3(){
    //ApplicationContext context =new ClassPathXmlApplicationContext("bean4.xml");
    ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("bean4.xml");
    Orders orders = context.getBean("orders", Orders.class);
    System.out.println("第四步,获取创建bean实例对象");
    System.out.println(orders);
    //手动销毁
    context.close();
}
<bean id="orders" class="com.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">    
 		 <property name="oname" value="shouji">
 		  </property>
</bean>

4.bean声明周期后置处理

  1. 通过构造器创建bean实例(无惨构造)

  2. 为bean的属性设置和其他bean引用(调用set方法)

  3. 把bean实例传递给bean后置处理器 postProcessBeforeInitialization

  4. 调用bean的初始化方法

  5. 把bean实例传递bean后置处理器的方法 postProcessAfterInitialization

  6. bean可以使用了

  7. 当容器关闭时候,调用bean的销毁的方法

  8. 演示添加后置处理器效果

    1. 创建类,实现接口BeanPostProcessor,创建后置处理器
public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return bean;
    }
}

7 IOC操作Bean管理(XML方式自动装配)

1 什么是自动装配

  1. 根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

  2. 演示自动装配过程

根据名称注入

<!--实现自动装配    
bean标签属性autowire,配置自动装配    
		autowire属性 常用两个值:            
					byName根据属性名称注入 注入bean的id值和属性名称一样            
					byType根据属性类型注入-->    
<bean id="emp" class="com.spring5.aotowire.Emp" autowire="byName">       
	<!-- <property name="dept" ref="dept"></property>-->    
</bean>    
<bean id="dept" class="com.spring5.aotowire.Dept"></bean>

根据类型注入

<bean id="emp" class="com.spring5.aotowire.Emp" autowire="byType">   
		<!-- <property name="dept" ref="dept"></property>-->
</bean>
<bean id="dept" class="com.spring5.aotowire.Dept"></bean>

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

  1. 直接配置数据库信息

    1. 配置德鲁伊连接池
    2. 引入德鲁伊连接池依赖jar包
        <!--直接配置连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">   
        	 		<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>    
         		<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>    
         		<property name="username" value="root"></property>    
         		<property name="password" value="root"></property>
         </bean>
    
  2. 引入外部文件配置数据库连接池

    1. 创建外部属性文件,properties格式文件,写数据库信息
    prop.driverClass=com.mysql.jdbc.Driverprop.url=jdbc:mysql://localhost:3306/userDbprop.userName=rootprop.password=root
    
    1. 把外部properties属性文件引入到Spring配置文件中

      引入context

      <?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:context="http://www.springframework.org/schema/context"      
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      

      在Spring配置文件中使用标签引入外部属性文件

      <!--引入外部属性文件-->
      <context:property-placeholder location="jdbc.properties"/>
      <!--配置连接池-->    
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <property name="driverClassName" value="${prop.driverClass}"></property>
              <property name="url" value="${prop.url}"></property>        
              property name="username" value="${prop.userName}"></property>        
              <property name="password" value="${prop.password}"></property>
        </bean>
      

9 IOC操作Bean管理(基于注解方式)

  1. 什么是注解

    1. 注解是代码特殊标记,格式:@注解名称
    2. 使用注解,注解作用在类,方法,属性
    3. 使用目的:简化xml配置
  2. Spring针对Bean管理中创建对象提供注解

    1. @Component
    2. @Service
    3. @Controller
    4. @Repository

    上述四个注解功能是一样的,都可以用来创建bean实例

  3. 基于注解方式实现对象创建

    1. 引入依赖
    2. 开启组件扫描
    <!--开启组件扫描    扫描多个包,多个包用逗号隔开com.spring5.dao,com.spring5.service    扫描包上层目录-->
    <context:component-scan base-package="com.spring5"></context:component-scan>
    

    3.创建类,在类上面创建对象注解

    //在注解里面value属性值可以省略不写
    //默认值是类名称,首字母小写
    @Service(value = "userService")//<bean id="UserService" class="....."
    public class UserService {
        public void add(){
            System.out.println("service add........");
        }
    }
    
  4. 开启组件扫描的细节

<!--示例1
    use-default-filters="false" 表示不使用默认filter,自己配置
    context:include-filter 设置扫描哪些内容
-->
<context:component-scan base-package="com.spring5" use-default-filters="false">
    <context:include-filter type="annotation"
                            expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例2
    下面配置扫描包所有内容
    context:exclude-filter 设置哪些内容不被扫描
-->
<context:component-scan base-package="com.spring5">
    <context:exclude-filter type="annotation"
                            expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

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

  1. @AutoWired: 根据属性类型进行自动装配

    1. 把service和dao 对象创建,在service和dao类添加创建对象注解
    2. 在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解
    @Service(value = "userService")//<bean id="UserService" class="....."
    public class UserService {
        //定义属性
        //不许要添加set方法
        //添加属性注解
        @Autowired
        private UserDao userDao;
        public void add(){
            System.out.println("service add........");
            userDao.add();
        }
    }
    
  2. @Qualifier:根据属性名称进行注入

    1. @Qualifier注解的使用,和@AutoWired一起使用
    //定义属性//不许要添加set方法//添加属性注解
    @Autowired
    @Qualifier(value = "userDaoImpl1")
    //根据名称进行注入
    private UserDao userDao;
    
  3. @Resource:根据类型注入,可以根据名称注入

    //@Resource
    @Resource(name = "userDaoImpl1")
    private  UserDao userDao;
    
  4. @Value:注入普通类型

    @Value(value = "zhangsan")
    private String name ;
    

6.完全注解开发

  1. 创建配置类,替代xml配置文件

    @Configuration//作为配置类,代替xml文件
    @ComponentScan(basePackages = {"com.spring5"})// 等价于<context:component-scan base-package="com.spring5"></context:component-scan>public class SpringConfig {}
    
  2. 编写测试类

    @Test
    public void testService2(){   
     //加载配置类   
     ApplicationContext context= new AnnotationConfigApplicationContext(SpringConfig.class);   
     UserService userService = context.getBean("userService", UserService.class);    
     System.out.println(userService);    
     userService.add();
    }
    

3 AOP

1 什么是AOP

  1. 面向切面编程(方面),利用aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用行,同时提高了开发的效率。
  2. 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
  3. 使用登录例子说明aop

在这里插入图片描述

2 AOP底层原理

1 AOP底层使用了动态代理

  1. 有两种情况的动态代理

    1. 有接口,使用JDK动态代理

      创建接口实现类代理对象,增强类的方法

在这里插入图片描述

  1. 没有接口,使用CGLIB动态代理

在这里插入图片描述

2 AOP(JDK动态代理)

  1. 使用jdk动态代理,使用proxy类里面的方法创建代理对象

    1. 调用newProxyInstance方法

      ? 有三个参数:

      ? 第一个参数,类加载器

      ? 第二个参数,增强方法所在的类,这个类实现的接口,支持多个接口

      ? 第三个参数,实现这个接口InvocaHandler,创建代理对象,写增强的方法

  2. 编写JDK动态代理代码

    1. 创建接口,定义方法
    public interface UserDao {
        public int add(int a,int b);
        public String update(String id);
        }
    
    1. 创建接口实现类,实现方法

      public class UserDaoImpl implements UserDao{
          @Override
          public int add(int a, int b) {
              return a+b;
          }
      
          @Override
          public String update(String id) {
              return id;
          }
      }
      
      1. 使用Proxy类创建接口代理对象
    package com.spring5;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.Arrays;
    
    public class JDKProxy {
        public static void main(String[] args) {
            //创建接口实现类代理对象
            Class[] interfaces={UserDao.class};
    //        Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
    //            @Override
    //            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //                return null;
    //              }
    //        });
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
            String ni = dao.update("ni");/* 方法之前执行....update:传递的参数...[ni]
                                                update方法执行了.....
                                                方法之后执行...com.spring5.UserDaoImpl@6f94fa3e
                                                id为:ni*/
            System.out.println("id为:"+ni);
            //int add = dao.add(1, 2);
            //System.out.println("结果为:"+add);
        }
    }
    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler{
        // 把创建的是谁的代理对象,把谁传递过来
        //有参构造传递
        private Object obj;
        public UserDaoProxy(Object obj){
            this.obj =obj;
        }
    
        //增强的逻辑
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //方法之前
            System.out.println("方法之前执行...."+method.getName()+":传递的参数..."+ Arrays.toString(args));
    
            //被增强的方法执行
            Object res = method.invoke(obj, args);
    
            //方法之后
            System.out.println("方法之后执行..."+obj);
            return res;
        }
    }
    

3 AOP(术语)

  1. 连接点

    类里面哪些方法可以被增强,这些方法称为连接点

  2. 切入点

    实际被正真增强的方法,称为切入点

  3. 通知(增强)

    1. 实际增强的逻辑部分称为通知(增强)
    2. 通知有多种类型
      1. 前置通知
      2. 后置通知
      3. 环绕通知
      4. 异常通知
      5. 最终通知 类似于try catch中的finally
  4. 切面

    是动作,把通知应用到切入点过程

4 AOP操作(准备)

  1. Spring框架中一般都只基于AspectJ实现AOP操作

    1. 什么是AspeJ

      AspeJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作

  2. 基于AspectJ实现AOP操作

    1. 基于xml配置文件实现
    2. 基于注解方式实现(使用)
  3. 在项目工程里面引入AOP相关依赖

  4. 切入点表达式

    1. 切入点表达式作用:知道对哪个类里面的哪个方法进行增强

    2. 语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]))

    3. 举例

      1. 对com.dao.BookDao类里面的add进行增强

        execution(*com.dao.BookDao.add(…))

      2. 对com.dao.BookDao类里面的所有方法进行增强

        execution(*com.dao.BookDao.(…))

      3. 对com.dao包里面所有类,所有方法进行增强

        execution( com.dao . . *(…) )

5 AOP操作(AspectJ注解)

  1. 创建类,在类里面定义方法

    public class User {
        public void add(){
            System.out.println("add......");
        }
    }
    
  2. 创建增强类(编写增强逻辑)

    1. 在增强类里面,创建方法,让不同方法代表不同的通知类型

      //增强的类
      public class UserProxy {
          
          //前置通知
          public void before(){
              System.out.println("before....");
          }
      }
      
  3. 进行通知配置

    1. 在Spring配置文件中,开启注解扫描

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:aop="http://www.springframework.org/schema/aop"
             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
                                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
              <!--开启注解扫描-->
          <context:component-scan base-package="com.spring5.aopanno"></context:component-scan>
      </beans>
      
    2. 使用注解创建User和UserProxy对象

      @Component
      public class User {
          public void add(){
                  System.out.println("add......");    
           }
       }
       @Component
      public class UserProxy {
           //前置通知    
           public void before(){
                   System.out.println("before....");    
            }
       }
      
    3. 在增强类上面添加注解@Aspect

      @Component
      @Aspect//生成代理对象
      public class UserProxy {
          //前置通知    
          public void before(){
                  System.out.println("before....");
          }
      

    }

    
    4. 在Spring配置文件中开启生成代理对象
    
    ```xml
    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
  4. 配置不同类型的通知

    1. 在增强类的里面,在作为通知方法上面,添加通知类型注解,使用切入点表达式配置

      @Component
      @Aspect//生成代理对象
      public class UserProxy {
          //前置通知    //@Before注解表示作为前置通知    
          @Before(value = "execution(* com.spring5.aopanno.User.add(..))")
           public void before(){
                   System.out.println("before....");    
            }
      

    }

    
    ```java
     *///增强的类
     @Component
     @Aspect
     //生成代理对象
     public class UserProxy {
         //前置通知    
         //@Before注解表示作为前置通知    
         @Before(value = "execution(* com.spring5.aopanno.User.add(..))")    
         public void before(){
                 System.out.println("before....");    
          }    
          //最终通知    
          @After(value = "execution(* com.spring5.aopanno.User.add(..))")   
           public void after(){
                   System.out.println("after.....");    
           }   
            //后置通知(返回通知)    
            @AfterReturning(value = "execution(* com.spring5.aopanno.User.add(..))")    
            public void afterReturning(){
                    System.out.println("afterReturning.....");    
            }    
            //异常通知    
            @AfterThrowing(value = "execution(* com.spring5.aopanno.User.add(..))")    
            public void afterThrowing(){
                    System.out.println("afterThrowing.....");    
             }    
             //环绕通知    
             @Around(value = "execution(* com.spring5.aopanno.User.add(..))")    
             public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
                     System.out.println("环绕之前.....");        
                      //被增强方法执行        
                      proceedingJoinPoint.proceed();        
                      System.out.println("环绕之后.....");    
              }
    }
    
  5. 相同切入点抽取

    //相同切入点抽取
    @Pointcut(value = "execution(* com.spring5.aopanno.User.add(..))")
    public void pointdemo(){    }
    //前置通知
    //@Before注解表示作为前置通知
    @Before(value = "pointdemo()")
    public void before(){ 
       System.out.println("before....");
     }
    
  6. 有多个增强类对同一个方法进行增强,设置增强类优先级

    1. 在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高

      @Component@Aspect@Order(1)public class PersonProxy @Component@Aspect//生成代理对象@Order(3)public class UserProxy 
      

7.完全使用注解开发

? 创建配置类,不需要创建xml配置文件

@Configuration
@ComponentScan(basePackages = {"com"})
@EnableAspectJAutoProxy(proxyTargetClass = true)//<context:component-scan base-package="com.spring5.aopanno"/>
public class ConfigAop {}

6 AOP操作(AspectJ配置文件)

  1. 创建两个类,增强类和被增强类,创建方法

    public class Book {    
       public void buy(){
              System.out.println("buy.......");    
       }
    }
        public class BookProxy {
                public void before(){
                        System.out.println("before.......");   
          }
    }
    
  2. 在Spring配置文件中创建两个类对象

    <!--创建对象-->
    <bean id="book" class="com.spring5.aopxml.Book"></bean><bean id="bookProxy" class="com.spring5.aopxml.BookProxy"></bean>
    
  3. 在Spring配置文件中配置切入点

    <!--配置aop增强-->
    <aop:config>
        <!--切入点-->    
        <aop:pointcut id="p" expression="execution(* com.spring5.aopxml.Book.buy(..))"/>    
        <!--配置切面-->    
        <aop:aspect ref="bookProxy">        
        <!--增强作用在具体的方法上-->        
        <aop:before method="before" pointcut-ref="p"/>    
        </aop:aspect>
    </aop:config>
    

4 JdbcTemplate

1 JdbcTemplate(概念和准备工作)

  1. 什么是JdbcTemplate

    1. Spring框架对jdbc进行了封装,使用JdbcTemplate方便实现对数据库操作
  2. 准备工作

    1. 引入相关jar包

    2. 在spring配置文件配置数据库连接池

      <!-- 数据库连接池 -->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"      destroy-method="close">
          <property name="url" value="jdbc:mariadb://localhost:3306/user_db" />   
          <property name="username" value="root" />    
          <property name="password" value="Xy072548." />    
          <property name="driverClassName" value="org.mariadb.jdbc.Driver" />
      </bean>
      
    3. 配置JdbcTemplate对象,注入DataSource

      <!--创建JdbcTemplate对象-->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <!--注入DataSource-->
          <property name="dataSource" ref="dataSource"></property>
      </bean>
      
    4. 创建service类,创建dao类,在dao注入jdbcTemplate对象

      1. 配置文件中

        <!--组件扫描-->
        <context:component-scan base-package="com"></context:component-scan>
        
      2. service

        @Service
        public class BookService {
            //注入dao
            @Autowired
            private BookDao bookDao;
        }
        
      3. dao

        @Repository
        public class BookDaoImpl implements BookDao{
            //注入JdbcTemplate
            @Autowired
            private JdbcTemplate jdbcTemplate;
        }
        

2 JdbcTemplate操作数据库

1 添加操作

  1. 对应数据库创建实体类

  2. 编写service和dao

    1. 在dao进行数据库添加操作

      @Repository
      public class BookDaoImpl implements BookDao{
          //注入JdbcTemplate    
          @Autowired    
          private JdbcTemplate jdbcTemplate;   
          @Override    
          public void add(Book book) {
                  String sql="insert into t_book values(?,?,?)";        
                  Object[] args ={book.getUserId(), book.getUsername(), book.getUstatus()};       
                   int update = jdbcTemplate.update(sql,args);        
                   System.out.println(update);    
           }
      

    }

    
    ?	
    
    2. 测试类
    
    ```java
    @Test
    public void testJdbcTemplate(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");   
        BookService bookService = context.getBean("bookService", BookService.class);    
        Book book = new Book();    
        book.setUserId("1");    
        book.setUsername("zhangsan");   
        book.setUstatus("a");    
        bookService.addBook(book);
    }
    

2 JdbcTemplate操作数据库(修改和操作)

//修改
@Override
public void updateBook(Book book) {
    String sql="update t_book set username=?,ustatus=?, where user_id=?";    
    Object[] args ={ book.getUsername(), book.getUstatus(),book.getUserId()};    
    int update = jdbcTemplate.update(sql, args);    
    System.out.println(update);}
//删除
@Override
public void deleteBook(String id) {
    String sql="delete from t_book where user_id=?";    
    int del = jdbcTemplate.update(sql, id);    
    System.out.println(del);
}

3 JdbcTemplate操作数据库(查询)

  1. 查询返回某个值

    1. 查询表里有多少条记录,返回值是某个值

      @Override
      public int selectCount() {
         String sql="select count(*) from t_book";    
         Integer count = jdbcTemplate.queryForObject(sql,Integer.class);   
          return count;
      

    }

    
    
  2. 查询返回对象

    1. 查询图书详情

    2. JdbcTemplate实现查询返回对象

      @Override
      public Book findBookInfo(String id) {
          String sql="select * from t_book where user_id=?";
          //调用方法
          //第二个参数RowMapper,是一个接口,返回不同类型,使用这个接口里面实现类完成数据封装
          Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
          return book;
      }
      
  3. 返回集合

    1. 查询图书列表分页

      @Override
      public List<Book> findAllBook() {
          String sql = "select * from t_book";
          List<Book> books = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
          return books;
      }
      

4 JdbcTemplate操作数据库(批量操作)

  1. 批量操作:操作表里面多条记录

  2. JdbcTemplate实现批量添加操作

    batchUpdate(String sql,List<Object[]> batchArgs)

    第一个参数:sql语句

    第二个参数:list集合,添加多条记录数据

    @Override
    public void batchAddBook(List<Object[]> batchArgs) {
        String sql = "insert into t_book values(?,?,?)";
        int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
        System.out.println(Arrays.toString((ints)));
    }
    
    List<Object[]> batchArgs = new ArrayList<>();
    Object[] o1 ={"3","java","q"};
    Object[] o2 ={"4","c++","w"};
    Object[] o3 ={"5","javascript","e"};
    batchArgs.add(o1);
    batchArgs.add(o2);
    batchArgs.add(o3);
    //调用批量添加
    bookService.batchAdd(batchArgs);
    
  3. JdbcTemplate实现批量修改操作

    @Override
    public void batchUpdateBook(List<Object[]> batchArgs) {
        String sql = "update t_book set username=?,ustatus=? where user_id=?";    
        int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);   
        System.out.println(ints);
     }
    
    List<Object[]> batchArgs = new ArrayList<>();
    Object[] o1 ={"java","s","3"};
    Object[] o2 ={"c#","z","4"};
    Object[] o3 ={"javascript","v","5"};
    batchArgs.add(o1);
    batchArgs.add(o2);
    batchArgs.add(o3);
    bookService.batchUpdate(batchArgs);
    

4.JdbcTemplate实现批量删除操作

@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
    String sql = "delete from t_book where user_id=?";    
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);    
    System.out.println(ints);
}
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 ={"3"};
Object[] o2 ={"5"};
batchArgs.add(o1);
batchArgs.add(o2);
bookService.batchDelete(batchArgs);

5 事务操作

1 场景引入

  1. 创建数据库表添加记录

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

  2. 创建service,搭建dao,完成对象创建和注入

    1. 在service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource

      @Service
      public class UserService {
          //注入dao    
          @Autowired   
          private UserDao userDao;
      }
      
      @Repository
      public class UserDaoImpl implements UserDao{
          @Autowired    
          private JdbcTemplate jdbcTemplate;
      }
      
      <!-- 数据库连接池 -->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"      destroy-method="close">
          <property name="url" value="jdbc:mariadb://localhost:3306/user_db" />    
          <property name="username" value="root" />    
          <property name="password" value="Xy072548." />   
          <property name="driverClassName" value="org.mariadb.jdbc.Driver" /></bean>
          <!--创建JdbcTemplate对象-->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">    
          <!--注入DataSource-->    
          <property name="dataSource" ref="dataSource"></property>
       </bean>
      
    2. 在dao创建两个方法:多钱和少钱的方法,在service创建方法(转账的方法)

      @Override
      public void addMoney() {
          String sql="update t_account set money=money+? where username=?";
          jdbcTemplate.update(sql,100,"marry");
      }
      
      @Override
      public void reduceMoney() {
          String sql="update t_account set money=money-? where username=?";
          jdbcTemplate.update(sql,100,"lucy");
      }
      
      @Service
      public class UserService {
          //注入dao
          @Autowired
          private UserDao userDao;
          
          //转账方法
          public void accountMoney(){
              //lucy少100
              userDao.reduceMoney();
              //marry多100
              userDao.addMoney();
          }
      }
      
    3. 上述代码正常执行,不会产生问题,出现异常就会有问题

      //转账方法
      public void accountMoney(){
          //lucy少100
          userDao.reduceMoney();
          //模拟异常
          int i =10/0;
          //marry多100
          userDao.addMoney();
      }
      

2 Spring事务管理介绍

  1. 事务添加到JavaEE service层

  2. 在Spring进行事务操作

    1. 有两种方式:编程式事务管理和声明式事务管理(使用)
  3. 声明式事务管理

    1. 基于注解方式(使用)
    2. 基于xml配置文件方式
  4. 在Spring进行声明式事务管理,底层使用AOP原理

  5. Spring事务管理API

    1. 提供了接口,代表事务管理器
      在这里插入图片描述

3 注解声明式事务管理

  1. 在Spring:配置事务管理器

    <!--创建事务管理-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    
    				<!--注入数据源-->    
    				<property name="dataSource" ref="dataSource">
    				</property>
    </bean>
    
  2. 在Spring配置文件,开启事务注解

    1. 在Spring配置文件引入名称空间

    2. 开启事务注解

      <!--开启事务注解-->
      <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
      
    3. 在service类上面(或者service类里面方法上面)添加事务注解

      1. @Transactional,可以添加到类上面,也可以添加到方法上面

      2. 添加到类上面,表示类里面所有方法都添加了事务

      3. 添加到方法上面,只有此方法添加了事务

        @Service
        @Transactional
        public class UserService
        

4 注解声明式事务管理参数配置

  1. 在service类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数
    在这里插入图片描述
  2. 名称解释
    isolation:事务隔离级别多事务操作之间不会产生影响
    timeout:超时时间事务在一定时间内进行提交,如果不提交就回滚,默认值是-1,设置时间以秒为单位
    readOnly:是否只读默认值false,可以查询,可以添加修改删除操作设置为:true后,只能查询
    rollbackFor:回滚设置出现哪些异常进行回滚
    noRollbackFor:不回滚设置出现哪些异常不进行回滚
    更多操作propagation:事务传播行为多事务方法之间进行调用,事务如何进行管理@Transactional(propagation = Propagation.REQUIRED)

5 XML声明式事务管理

  1. 在Spring配置文件中进行配置

    1. 配置事务

    2. 配置通知(增强的地方叫通知)

    3. 配置切入点和切面

      <!--1 创建事务管理-->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <!--注入数据源-->
          <property name="dataSource" ref="dataSource"></property>
      </bean>
      
      <!-- 2 配置通知-->
      <tx:advice id="txadvice">
          <!--配置事务参数-->
          <tx:attributes>
              <!--哪种规则的方法上面添加事务-->
              <tx:method name="accountMoney" propagation="REQUIRED"/>
          </tx:attributes>
      </tx:advice>
      <!--3 配置切入点和切面-->
      <aop:config>
          <!--配置切入点-->
          <aop:pointcut id="pt" expression="execution(* com.spring5.service.UserService.*(..))"/>
          <!--配置切面-->
          <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
      </aop:config>
      

6 完全注解声明事务管理

  1. 创建配置类,使用配置类代替xml配置文件

    @Configuration//配置类
    @ComponentScan(basePackages = "com.spring5")//开启组件扫描
    @EnableTransactionManagement//开启事务
    public class TxConfig {
    
        //创建数据连接池
        @Bean
        public DruidDataSource getDDruidDataSource(){
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName("org.mariadb.jdbc.Driver");
            dataSource.setUrl("jdbc:mariadb://localhost:3306/user_db");
            dataSource.setUsername("root");
            dataSource.setPassword("Xy072548.");
            return dataSource;
        }
        //创建JdbcTemplate对象
        @Bean
        public JdbcTemplate getJdbcTemplate(DataSource dataSource){
            //到IOC容器中根据类型找到dataSource
            JdbcTemplate jdbcTemplate = new JdbcTemplate();
            //注入dataSource
            jdbcTemplate.setDataSource(dataSource);
            return jdbcTemplate;
        }
    
        //创建事务管理器
        @Bean
        public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
            DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
            transactionManager.setDataSource(dataSource);
            return transactionManager;
        }
    }
    

5 Spring框架新功能

  1. 整个Spring5框架的代码基于java8,运行时兼容JDK9,许多不建议使用的类和方法在整个代码库中删除

Spring5 框架自带了通用的日志封装

  1. Spring5已经移除了Log4jConfigListener,官方建议使用Log4j2
  2. Spring框架整合Log4j2

引入jar包

在这里插入图片描述
创建Log4j2.xml

<?xml version="1.0" encoding="UTF-8"?><!--日志级别以及优先级排序:
 OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="INFO">   
 	<!--先定义所有的appender-->    
 	<appenders>       
  			<!--输出日志信息到控制台-->
          <console name="Console" target="SYSTEM_OUT">
                   <!--控制日志输出的格式-->
                  <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
           </console>
	</appenders>
	<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
 	<!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
 	<loggers> 
             <root level="info">   
                    <appender-ref ref="Console"/>  
               </root> 
	</loggers>
</configuration>

Spring框架核心容器支持@Nullable注解

  1. @Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回,属性值,参数值可以为空

  2. 注解用在方法上面,返回值可以为空

    @Nullable
    String getId();
    
  3. 注解使用在方法参数里面,方法参数可以为空
    在这里插入图片描述

  4. 注解使用在属性值上面,属性值可以为空

    @Nullable
    private String name;
    

Spring5 核心容器支持函数式风格GenericApplicationContext

//函数式创建对象交给Spring进行管理
@Test
public void testGenericApplicationContext(){
    //创建GenericApplicationContext对象
    GenericApplicationContext context = new GenericApplicationContext();
    //调用context的方法对象注册
    context.refresh();
    //context.registerBean(User.class,() -> new User());
    context.registerBean("user1",User.class,() -> new User());
    //获取在Spring注册的对象
    //User user = context.getBean("com.spring5.test.User");
    User user = (User) context.getBean("user1");
    System.out.println(user);
}

Spring5支持整合Junit5

  1. 整合Junit4

    @RunWith(SpringJUnit4ClassRunner.class)//单元测试框架
    @ContextConfiguration("classpath:bean1.xml")//加载配置文件
    public class JTest4 {
        @Autowired
        private UserService userService;
    
        @Test
        public void  test1(){
            userService.accountMoney();
        }
    }
    
  2. 整合Junit5

    引入jar包

    @ExtendWith(SpringExtension.class)
    @ContextConfiguration("classpath:bean1.xml")//加载配置文件
    class JTest5 {
        @Autowired
        private UserService userService;
    
        @Test
        public void  test1(){
            userService.accountMoney();
        }
    }
    
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:15:31  更:2021-11-20 18:16:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:28:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码