锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Spring框架详解

时间:2024-01-02 10:37:15 q24j6a连接器

简介

Spring5框架

内容介绍:

1.Spring概念

2.IOC容器

3.Aop

4.JDBCTEmplate

5.事物管理

6.Spring5新特性



一.Spring框架概述


1.概述


1.Spring框架为轻量级JavaEE框架

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

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

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

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

4.Spring特点

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

(2)Aop变成支持

(3)方便程序测试

(4)与其他框架集成方便

(5)方便事物操作

(6)降低API开发难度

5.Spring5



2.入门案例

(1)下载spring

image-20220314143447272

最后是这个网站

https://repo.spring.io/ui/native/release/org/springframework/spring/ 

下载解压

(2)创建新项目

(3)导入jar包

[外链图片转存失败,源站可能有防盗链机制,建议保存图片并直接上传(img-SWSNjI6C-1649754754216)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220314212314473.png)]

把所需的jar包导入其中

导入流程:

建立在项目文件夹中lab文件夹

把jar将包放入文件夹中

(4)创建普通类

在这一类中创建普通方法

(5)创建Spring配置文件

在配置文件中配置创建的对象

1.Spring使用配置文件xml文件格式

(6)编写测试代码

二.IOC容器

1.IOC底层原理

(1)什么是IOC

控制反转(Inversion of Control,缩写为IoC),它是面向对象编程的设计原则,可用于降低计算机代码之间的耦合。最常见的方法是依赖注入(Dependency Injection,简称DI),还有一种方法叫依赖搜索(Dependency Lookup)。通过控制逆转,当对象被创建时,调节系统中所有对象的外部实体将所依赖对象的引用传递给它。也可以说,依赖被注入对象。 

one:控制反转,将对象的创建和调用过程交给对象Spring进行管理

two:使用IOC目的:降低耦合度

three:入门案例是IOC的实现

(2)IOC底层原理

(1)xml分析、工厂模式、反射

(3)画图讲解IOC底层原理

[外链图片转存失败,源站可能有防盗链机制,建议保存图片并直接上传(img-SDr4j6ah-1649754754217)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220316111726329.png)]

IOC过程

(1)配置xml文件配置创建的对象

(2)有service类和dao创建工厂类


2.IOC接口(BeanFactory)

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

2.Spring提供IOC容器实现的方法有两种:(两个接口

(1)BeanFactory:

IOC容器中最基本的实现方法Spring不提供开发人员使用内部接口

**特点:**加载配置文件时不会创建对象,只有在获取对象(使用)时才会创建对象

(2)ApplicationContext:

BeanFactory接口的子接口提供越来越强大的功能,通常由开发人员使用

**特点:**在加载配置文件时,将创建配置文件的对象

3.ApplicationContext接口有实现类

FlieSystemXmlApplicationContext对应电脑的盘符路径

ClassPathXmlApplicationContext类路径


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

(1)Bean管理定义:

Bean管理是指两个操作

1.Spring创建对象

2.Spring注入属性

(2)Bean两种管理操作方式

1.基于xml创建对象的方法  2.基于注释方法的实现 

1.基于xml实现文件配置模式

      

(1)在Spring中使用bean在标签中添加相应的属性可以创建对象

(2)在bean标签中有许多属性,介绍常用属性

*id属性:唯一的标识

*class属性:类全路径(包类路径)

*name属性:和id一样,但是在name可以添加一些特殊符号

(3)创建对象时,默认执行无参数结构方法

2.基于xml注入属性的方式

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

3.第一种注射方式:使用set注入方法

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

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

最后测试:

4.第二种注入方式:通过参考结构注入

(1)创建类,定义属性,创建属性对应参数结构方法

(2)在Spring配置在文件中

测试:

5.p注入名称空间(理解)

(1)注入P名空间可以简化xml配置方式

第一步:在配置文件中添加p名空间

第二步:注入属性,在bean操作标签

测试:

(3)IOC操作Bean管理(xml注入其他类型的操作)

字面量

one:null值

eg:

测试:

two:属性值包含特殊符号
1.把<>进行转义<>

2.把带特殊符号内容写到CDATA

测试:(两个的输出结果都一样)

three:注入属性-外部bean

1.创建两个类service和dao类

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

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

测试:

four:注入属性-内部bean
  1. 一对多关系:部门和员工

    一个部门有多个员工,一个员工属于一个部门

    部门是一,员工是多

  2. 在实体类之间表示一对多的关系,员工表示所属部门,使用对象类型属性进行表示

  3. 在Spring的配置文件中进行配置

测试:

five:注入属性-级联赋值

1.第一种写法

测试:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SceNe7Ei-1649754754226)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220317202126805.png)]

2.第二种写法

Dept.java

Testbean.java同上

测试:


(4)IOC操作Bean管理(xml注入集合属性)

  1. 注入数组类型属性

  2. 注入List集合类型属性

  3. 注入Map集合类型属性

1.创建类

定义数组,List,Map,Set类型的属性,生成对应的set方法

package com.spring.collectiontype;

import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author yanchaochao
 * @date 2022/3/17 20:34
 */
public class Stu {
    //1.数组类型
    private String[] courses;

    //2.list集合类型属性
    private List list;

    //3.创建Map集合属性
    private Map maps;

    //4.set集合类型
    private Set sets;



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

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

    public void setMaps(Map maps) {
        this.maps = maps;
    }

    public void setSets(Set sets) {
        this.sets = sets;

    }

    //测试
    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
    }
}
2.在spring配置文件进行配置




        
        

                
                
                        
                                java
                                c
                                c++
                                算法
                                mysql
                        
                

                
                
                        
                                张三
                                小三
                        
                

                
                
                        
                                
                                
                        
                

                
                
                       
                               MySQL
                               Redis
                       
                
        

测试:

package com.spring.testdemo;

import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 21:19
 */
public class Testcollectiontype {
    @Test
    public void testCollection(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Stu stu = context.getBean("stu", Stu.class);
        stu.test();

    }
}
3.在集合里设置对象类型值

        
                
        
        
                
        



 
                
                        
                                
                                
                        
                


Course.java


package com.spring.collectiontype;

/**
 * @author yanchaochao
 * @date 2022/3/17 21:40
 */
public class Course {
    private  String cname;//课程名称

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

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + ''' +
                '}';
    }
}



Stu.java


package com.spring.collectiontype;

import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author yanchaochao
 * @date 2022/3/17 20:34
 */
public class Stu {
    //1.数组类型
    private String[] courses;

    //2.list集合类型属性
    private List list;

    //3.创建Map集合属性
    private Map maps;

    //4.set集合类型
    private Set sets;

    //学生所学多门课程
    private ListcourseList;
    public void setCourseList(List courseList) {
        this.courseList = courseList;
    }

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

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

    public void setMaps(Map maps) {
        this.maps = maps;
    }

    public void setSets(Set sets) {
        this.sets = sets;

    }

    //测试
    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
        System.out.println(courseList);
    }
}


bean1.xml





        
        

                
                
                        
                                java
                                c
                                c++
                                算法
                                mysql
                        
                

                
                
                        
                                张三
                                小三
                        
                

                
                
                        
                                
                                
                        
                

                
                
                       
                               MySQL
                               Redis
                       
                

                
                
                        
                                
                                
                        
                
        
        
        
                
        
        
                
        



Testcollectiontype.java


package com.spring.testdemo;

import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 21:19
 */
public class Testcollectiontype {
    @Test
    public void testCollection(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Stu stu = context.getBean("stu", Stu.class);
        stu.test();

    }
}

测试:

4.把集合注入的部分提取出来

(1)在spring配置文件中引入名称空间util

(2)使用util标签完成list集合注入提取

Book.java


package com.spring.collectiontype;
import java.util.List;
/**
 * @author yanchaochao
 * @date 2022/3/17 21:55
 */
public class Book {
    private Listlist;
    public void setList(List list) {
        this.list = list;
    }
    public void test(){
        System.out.println(list);
    }
}


bean2.xml





        
        
            JAVA
            C
            MySQL
            C++
            Git
        

        
        
            
        

测试:

package com.spring.testdemo;

import com.spring.collectiontype.Book;
import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 22:03
 */
public class TestBook {
    @Test
    public void testBook(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.test();

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JH1BJ9hR-1649754754228)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220317221208513.png)]


(5)IOC操作Bean管理(FactoryBean)

  1. Spring有两种类型Bean,一种普通bean,另外一种工厂bean(FactoryBean)

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

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

    第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean

    第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型

    MyBean.java

    package com.spring.factorybean;

    import com.spring.collectiontype.Course;
    import org.springframework.beans.factory.FactoryBean;

    /**

    • @author yanchaochao

    • @date 2022/3/17 22:21
      */
      public class MyBean implements FactoryBean {

      //定义类型和返回类型不一样
      //定义返回bean
      @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();
      }
      }

    bean3.xml

    
    
    
    

测试:

package com.spring.testdemo;

import com.spring.collectiontype.Course;
import com.spring.collectiontype.Stu;
import com.spring.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 22:23
 */
public class Testfactorybean {
    @Test
    public void testFactoryBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);

    }
}

(6)IOC操作Bean管理(Bean的作用域)

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

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

由图可得出,输出的两个地址是一样的,所以可以得出在默认情况下bean是单实例对象

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

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

(2)scope属性值

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

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

测试:

两个对象的地址不一样

(3)singleton和prototype区别

  1. singleton表示单实例,prototype表示多实例

  2. 设置scope值是singleton时候,加载spring的时候就会创建单实例对象

    设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法创建多实例对象

(7)IOC操作Bean管理(生命周期)

1.生命周期

从对象到对象销毁的过程

2.bean生命周期

(1)通过构造器创建bean实例(无参数构造)

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

(3)调用bean的初始化的方法(需要进行配置)

(4)bean可以直接使用了(对象获取到了)

(5)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁)

3.演示bean的生命周期
Order.java


package com.spring.bean;

/**
 * @author yanchaochao
 * @date 2022/3/18 19:48
 */
public class Order {
    private String oname;


    //无参数构造
    public Order(){
        System.out.println("第一步,执行无参构造实例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步,调用set方法调用初始化值");
    }

    //创建执行初始化的方法
    public void initMethod(){
        System.out.println("第三部,执行初始化方法");
    }

    //执行销毁的方法
    public void destroyMethod(){
        System.out.println("第五步执行销毁的方法");
    }
}


bean4.xml






    
        

    


测试:

Testbean.java


package com.spring.testdemo;

import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/18 19:54
 */
public class Testbean {
    @Test
    public void testBook(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Order order = context.getBean("orders", Order.class);
        System.out.println("第四步,得到对象");
        System.out.println(order);


        //手动销毁
        context.close();
    }
}

4.bean的后置处理

(1)通过构造器创建bean实例(无参数构造)

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

(3)把bean实例传递bean后置处理器的方法

postProcessBeforeInitialization

(4)调用bean的初始化的方法(需要进行配置)

(5)把bean实例传递bean后置处理器的方法

postProcessAfterInitialization

(6)bean可以直接使用了(对象获取到了)

(7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁)

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

(1)创建类,实现接口BeanPostProcessor,创建后置处理器

MyBeanPost.java


package com.spring.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;

/**
 * @author yanchaochao
 * @date 2022/3/18 20:17
 */
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;
    }
}


Order.java


package com.spring.bean;

/**
 * @author yanchaochao
 * @date 2022/3/18 19:48
 */
public class Order {
    private String oname;


    //无参数构造
    public Order(){
        System.out.println("第一步,执行无参构造实例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步,调用set方法调用初始化值");
    }

    //创建执行初始化的方法
    public void initMethod(){
        System.out.println("第三部,执行初始化方法");
    }

    //执行销毁的方法
    public void destroyMethod(){
        System.out.println("第五步执行销毁的方法");
    }
}


bean4.xml






    
        

    
    
    



Testbean.java


package com.spring.testdemo;

import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author yanchaochao
 * @date 2022/3/18 19:54
 */
public class Testbean {
    @Test
    public void testBook(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Order order = context.getBean("orders", Order.class);
        System.out.println("第四步,得到对象");
        System.out.println(order);

        //手动销毁
        context.close();
    }
}

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

1.什么是自动装配

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

2.演示自动装配

(1)根据属性名称自动注入

 
    

根据属性名称注入,注入值bean的id值和类属性名称一样

(2)根据属性类型自动注入

   
    

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

1.直接配置数据库信息

(1)配置德鲁伊连接池

 
    
        
        
        
        
    
2.引入外部属性文件配置数据库连接池

(1)创建外部属性文件,properties格式文件,写数据库信息

(2)把外部properties属性文件引入到配置文件

*引入context名称空间



(3)在spring配置文件中使用标签引入外部属性文件





    
        
        
        
        
    

4.IOC操作Bean管理(基于注解)

1.什么是注解

(1)注解是代码特殊标记,格式:@注解名称**(属性名称=属性值,属性名称=属性值)**

(2)使用注解,注解作用在类上面,方法上面,属性上面

(3)使用注解目的:简化xml配置

2.Spring针对Bean管理中创建对象提供注解

(1)@Component

(2)@Service

(3)@Controller

(4)@Repository

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

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

(1)引入依赖

(2)开启组件扫描

(3)创建类,在类上面添加创建对象注解

package com.atguigu.spring5.testdemo;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/22 14:31
 */
public class TestSpring5Demo1 {


    @Test
    public void testService(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

实例一:

实例二:

4.基于注解方式实现属性注入

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

第一步:把service和dao对象创建,在service和dao类添加创建对象注解

第二步:在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解

@Service
public class UserService {
    //定义dao类型的属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired
    private UserDao userDao;
    public void add(){
        System.out.println("service add.....");
        userDao.add();
    }
}


UserDao.java


package com.atguigu.spring5.dao;
public interface UserDao {
    public void add();
}


UserDaoImpl


import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add(){
        System.out.println("dao add...");
    }
}


UserService.java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    //定义dao类型的属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired
    private UserDao userDao;

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

测试:

TestSpring5Demo1.java


package com.atguigu.spring5.testdemo;

import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5Demo1 {
    @Test
    public void testService(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

(2)@Qualifier:根据属性名称进行注入

这个@Qualifier注解的使用,和上面@Autowired一起使用

(3)@Resource:可以根据类型注入,可以根据名称注入

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

5.完全注解开发

(1)创建配置类,替代xml的配置文件

package com.atguigu.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration  //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.atguigu"})
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();
    }


三.AOP

1.简介

AOP(面向切面编程)

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

主要功能

日志记录,性能统计,安全控制,事务处理,异常处理等等。

主要意图

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

eg:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZDxwnkh-1649754754232)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220322201401950.png)]

2.底层原理

一,AOP底层使用动态代理

(1)有两种情况

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

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

第二种:没有接口的情况,使用CGLIB代理

创建子类的代理对象,增强类的方法

3.AOP(JDK动态代理)

一,使用JDK动态代理,使用Proxy类里面的方法创建代理对象

调用newProxyInstance方法

方法里有三个参数:

one:类加载器

two:增强方法所在的类,这个类实现的接口,支持多个接口

three:实现这个接口InvocationHandler,创建代理对象,写增强的方法

二,JDK动态代理代码

(1)创建接口,定义方法

package com.study;

public interface UserDao {

    public int add(int a,int b);

    public String update(String id);

}

(2)创建接口实现类,实现方法

package com.study;

public class UserDaoImpl implements UserDao{

    @Override
    public int add(int a, int b) {
        System.out.println("add方法执行了......");
        return a+b;
    }

    @Override
    public String update(String id) {
        System.out.println("update方法执行了......");
        return id;
    }
}

(3)使用Proxy类创建接口代理对象

package com.study;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author yanchaochao
 * @date 2022/3/22 20:39
 */
public class JDKProxy {
    public static void main(String[] args) {
        //创建接口实现类代理对象
        Class [] interfaces = {UserDao.class};

        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));

        int result = dao.add(1,2);
        System.out.println("result:"+result);
    }
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{

    //1.把创建的是谁的代理对象,把谁传递过来
    //有参数构造传递
    private Object object;
    public UserDaoProxy(Object object){
        this.object = object;
    }


    //增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //方法之前
        System.out.println("方法之前执行......"+method.getName()+":传递参数..."+ Arrays.toString(args));

        //被增强的方法
        Object res = method.invoke(object, args);

        //方法之后
        System.out.println("方法执行之后......"+object);
        return res;
    }
}

结果:

4.AOP(术语)

一,连接点

二,切入点

三,通知(增强)

四,切面

5.AOP操作(准备)

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

(1)什么是AspectJ

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

2.基于AspectJ实现AOP操作

(1)基于xml配置文件实现

(2)jiyu注解方式实现

3.在项目工程里面引入AOP相关依赖

4.切入点表达式

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


(2)语法结构:

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

举例1:对com.atguigu.dao.BookDao类里面的add进行增强

execution(*com.atguigu.dao.BookDao.add(…方法中的参数))

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

execution(*com.atguigu.dao.BookDao. * (…方法中的参数))

举例3:对com.atguigu.dao包里面的所有类,类里面的所有方法进行增强

execution(*com.atguigu.dao. *. * (…方法中的参数))


6.AOP操作(AspectJ注解)

1.创建类,在类里面定义方法
2.创建增强类(编写增强逻辑)

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

package com.study.aopanno;
import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {
    public void add (){
        System.out.println("add...");
    }
}


package com.study.aopanno;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect  //生成代理对象
public class UserProxy {

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

(1)在spring配置文件中,开启注解扫描

bean1.xml




    
    
    

(2)使用注解创建User和UserProxy对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1btLVhd8-1649754754235)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220323175417167.png)]

(3)在增强类上面添加注解@Aspect

(4)在spring配置文件中开启代理生成对象



4.配置不用类型的通知

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

package com.study.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author yanchaochao
 * @date 2022/3/23 17:34
 */

//增强的类
@Component
@Aspect  //生成代理对象

public class UserProxy {



    //前置通知
    //Before注解表示为前置通知
    @Before(value = "execution(* com.study.aopanno.User.add(..))")

    public void before(){
        System.out.println("before......");
    }
    //最终通知
    @After(value = "execution(* com.study.aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning......");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing......");
    }

    //环绕通知
    @Around(value = "execution(* com.study.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("环绕之前......");


        //被增强的方法
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后......");
    }
}

TestAop.java

package com.study.test;

import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {



    @Test
    public void testAopAnno(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xnZT7SSR-1649754754236)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220323225111843.png)]

5.公共切入点抽取
package com.study.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect  //生成代理对象

public class UserProxy {




    //相同切入点抽取
    @Pointcut(value = "execution(* com.study.aopanno.User.add(..))")
    public void piontdemo(){

    }


    //前置通知
    //Before注解表示为前置通知
    @Before(value = "piontdemo()")

    public void before(){
        System.out.println("before......");
    }
    //最终通知
    @After(value = "execution(* com.study.aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning......");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing......");
    }

    //环绕通知
    @Around(value = "execution(* com.study.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("环绕之前......");
        //被增强的方法
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后......");
    }
}

6.有多个增强类多同一个方法进行增强,设置增强类优先级

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

PersonPerxy.java


package com.study.aopanno;


import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonPerxy {
     //后置通知(返回通知)
        @Before(value = "execution(* com.study.aopanno.User.add(..))")
        public void afterReturning(){
            System.out.println("Person Before......");
        }
}


User.java


package com.study.aopanno;
import org.springframework.stereotype.Component;

//被增强的类
@Component
public class User {
    public void add (){
        System.out.println("add...");
    }
}


UserProxy.java


package com.study.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


//增强的类
@Component
@Aspect  //生成代理对象
@Order(3)
public class UserProxy {




    //相同切入点抽取
    @Pointcut(value = "execution(* com.study.aopanno.User.add(..))")
    public void piontdemo(){

    }


    //前置通知
    //Before注解表示为前置通知
    @Before(value = "piontdemo()")

    public void before(){
        System.out.println("before......");
    }
    //最终通知
    @After(value = "execution(* com.study.aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning......");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing......");
    }

    //环绕通知
    @Around(value = "execution(* com.study.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("环绕之前......");


        //被增强的方法
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后......");
    }
}

测试:

package com.study.test;

import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
    @Test
    public void testAopAnno(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();

    }
}

7.AOP操作(AspectJ配置文件)

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

package com.study.aopxml;


public class Book {
    public void buy(){
        System.out.println("buy.......");
    }
}


package com.study.aopxml;

public class BookProxy {
    public void Before(){
        System.out.println("before.......");
    }
}

(2)在spring配置文件中创建两个类对象

(3)在spring配置文件中配置切入点




    
    




    
        
        
        
        
            
            
        


    

测试:

@Test
    public void testBook(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.buy();

    }


完全使用注解开发

不需要创建xml文件

package com.study.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;


@Configuration

@ComponentScan(basePackages = {"com.study"})

@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
    
}


四.JdbcTemplate

1.概念和准备

1.什么是JdbcTemplate

Spring框架对JDBC进行封装,使用JdbcTemplate方便对实现数据库操作

2.准备工作

(1)引入相关的jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iHCSmQ2K-1649754754237)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220328152239741.png)]

(2)在Spring配置文件中配置数据库的连接池


    
        
        
        
        
    

(3)JdbcTemplate对象,注入DataSource


    
        
        
    

(4)创建service类,创建dao类,在dao注入jdbcTemplate对象

配置文件中开启组件扫描


    

service

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

dao

@Repository
public interface BookDao {

}


public class BookDaoImpl implements BookDao{

    //注入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
}

2.JdbcTemplate操作数据库

(1)添加

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

2.编写service和dao

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

(2)调用jdbcTemplate对象里面的update方法实现

*有两个参数

*第一个参数:sql语句

*第二个参数:可变参数,设置sql语句值

public class BookDaoImpl implements BookDao{


    //注入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void add(Book book) {
        //1.创建sql语句
        String sql = "insert into t_book values(?,?,?)";

        //2.调用方法实现
        Object [] args = {book.getUserId(),book.getUsername(),book.getUstatus()};
        int update = jdbcTemplate.update(sql,args);
        //用法不一
//      int update = jdbcTemplate.update(sql,book.getUserId(),book.getUsername(),book.getUstatus());
        System.out.println(update);
    }
}

测试类Test:

package com.study.test;

import com.study.entity.Book;
import com.study.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/4/10 10:58
 */
public class TestBook {
    @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("ja

相关文章