Spring5 框架

Spring5 框架,第1张

Spring5 框架 一、Spring 概念

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

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

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

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

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

4、 Spring 特点 :

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

(2) Aop 编程支持

(3)方便程序测试

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

(5)方便进行事务 *** 作

(6)降低 API 开发难度

二、IOC 容器 1.IOC的底层原理
  • IOC:

    ①控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理

    ②使用 IOC 目的:为了耦合度降低

  • 底层原理: xml解析、工厂模式、反射

  • 讲解:最原始的方法如下,使用工厂模式可以降低耦合但不是降低到最低限度

  • 在Spring中,使用 IOC 容器可以降低耦合.使用IOC对当前进行改造

  • IOC 实现过程:

    • 第一步,xml 配置文件,配置创建的对象

    • <bean id="user" class="com.syy.spring5.User">bean>
      
    • 第二步,有 service 类和 dao 类,创建工厂类

    • class UserFactory{
      	public static UserDao getDao(){
              //1.xml解析,得到bean中class属性的值
              String classValue = class属性值;
              //2.通过反射创建对象
              Class clazz = Class.forName(classValue);//通过反射得到字节码文件
              return (UserDao)clazz.newInstance();//创建对象
          }
      }
      
2.IOC接口( BeanFactory )
  • IOC 的思想基于 IOC 容器完成,IOC 容器底层就是对象工厂

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

    • BeanFactory : IOC 容器最基本实现,是Spring内部的使用接口,不提供开发人员进行使用

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

    • ApplicationContext : BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人员使用

      注:在加载配置文件的时候就会把配置文件中的对象进行创建

  • ApplicationContext的主要实现类

    • FileSystemXmlApplicationContext
      • 需要写文件在系统中的位置(带盘符路径),文件全路径
    • ClassPathXmlApplicationContext
      • 路径为src内的文件,类路径
3.IOC *** 作Bean管理的概念
  • 什么是Bean管理
    • Bean管理指的是两个 *** 作:
      • Spring 创建对象
      • Spring 注入属性 – 设置值
  • Bean 管理 *** 作的两种方式
    • 基于 xml 配置文件方式实现
    • 基于注解方式实现
4.IOC *** 作Bean管理(基于xml) (1) 基于 xml 方式创建对象
  • <bean id="user" class="com.syy.spring5.User">bean>
    
  • 在Spring配置文件中,使用 bean 标签,标签中添加对应属性,就可以实现对象创建

  • 常用的属性:

    • id 属性:唯一标识(别名),通过标识获取对象,不能加特殊符号
    • class 属性:类全路径(包类路径)
    • name 属性:和id相同,但可以加特殊符号.不常用
  • 创建对象时,默认是执行无参构造方法完成对象创建

(2) 基于xml方式注入属性 – 需要在创建对象的基础上才能使用
  1. DI : 依赖注入,就是注入属性
  2. 注入方式:

    2.1 使用set方法进行注入

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

      public class User {
          //定义属性
          private String uname;
          private Integer age;
          //创建对应的set方法
          public void setUname(String uname) {
              this.uname = uname;
          }
          public void setAge(Integer age) {
              this.age = age;
          }
      }
      
    • 在Spring配置文件配置对象创建,配置属性注入

      <bean id="user" class="com.syy.spring5.User">
      
            <property name="uname" value="lili">property>
            <property name="age" value="11">property>
        bean>
    

    2.2 使用有参数构造进行注入

    • 创建类,定义属性,创建属性对应有参构造方法
    public class User {
        private String uname;
        private Integer age;
        //有参构造方法
        public User(String uname, Integer age) {
            this.uname = uname;
            this.age = age;
        }
      }
    
    • 在Spring配置文件中进行配置
        <bean id="user" class="com.syy.spring5.User">
            
            <constructor-arg name="uname" value="张三">constructor-arg>
            <constructor-arg name="age" value="54">constructor-arg>
        bean>
    

    2.3 p名称空间注入(了解)

    • p名称空间注入底层也是set方法注入,只是简化了xml配置方法
    • 第一步,添加p名称空间在配置文件中 – 将下行代码添加到 beans 标签中
      xmlns:p="http://www.springframework.org/schema/p"
    
    • 第二步,进行属性注入,在bean标签里面进行 *** 作
     <bean id="user" class="com.syy.spring5.User" p:uname="李四" p:age="12">bean>
    
  3. xml 注入其他类型属性

    3.1 字面量 – 属性的固定值

    • null值
      <property name="address">
                <null/>
            property>
    
    • 属性包括特殊符号 – 例<<南京>>

      • 将<>进行转义: < ; >
      • 将带特殊符号内容写到CDATA
       <property name="address">
              <value>>]]>value>
              property>
      

    3.2 注入外部属性 – 外部bean

    3.2.1 创建两个类service类和dao类

    3.2.2 在service调用dao里面的方法 – 引入外部bean

    • UserDao代码:
    public interface UserDao {
        void update();
    }
    
    • UserDaoImpl代码:
    public class UserDaoImpl implements UserDao {
        @Override
        public void update() {
            System.out.println("dao update......");
        }
    }
    
    
    • UserService代码:
    public class UserService {
        //创建UserDao类型属性,生成set方法
        private UserDao userDao;
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
        public void add(){
            System.out.println("service add ...........");
            //调用dao中方法
            userDao.update();
        }
    }
    

    3.2.3 在Spring配置文件中进行配置

    
        <bean id="userService" class="com.syy.spring5.service.UserService">
            
            <property name="userDao" ref="userDaoImpl">property>
        bean>
        
        <bean id="userDaoImpl" class="com.syy.spring5.dao.impl.UserDaoImpl">bean>
    
    

    3.3 注入外部属性 – 内部bean

    3.3.1 举例说明:在数据库中有

    • 一对多关系:部门和员工
      • 一个部门有多个员工,一个员工属于一个部门
    • 在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

    3.3.2 内部bean的实现

    ①创建部门类和员工类

    部门类:

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

    员工类:

    public class Emp {
        private String ename;
        private String gender;
        //员工属于某一个部门,使用对象形式表示
        private Dept dept;
        public void setEname(String ename) {
            this.ename = ename;
        }
        public void setGender(String gender) {
            this.gender = gender;
        }
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    }
    

    ②在Spring配置文件中进行配置

     <bean id="emp" class="com.syy.spring5.Emp">
            
            <property name="ename" value="lucy">property>
            <property name="gender" value="">property>
            
            <property name="dept">
                
                <bean id="dept" class="com.syy.spring5.Dept">
                    <property name="dname" value="安保部">property>
                bean>
            property>
        bean>
    

    3.4 注入外部属性 – 级联赋值

    级联赋值:同时向有关联的类中赋值(向多个实体类赋值)

    • 第一种写法:部门类和员工类代码不变,配置文件修改为:
      <bean id="emp" class="com.syy.spring5.Emp">
            
            <property name="ename" value="lucy">property>
            <property name="gender" value="">property>
            
            <property name="dept" ref="dept">property>
        bean>
        <bean id="dept" class="com.syy.spring5.Dept">
            <property name="dname" value="财务部">property>
        bean>
    
    • 第二写法:

      • 在Emp类中生成dept的get方法,用来得到对象

      • 配置文件修改

        <bean id="emp" class="com.syy.spring5.Emp">
              
              <property name="ename" value="lucy">property>
              <property name="gender" value="">property>
              
              <property name="dept" ref="dept">property>
              <property name="dept.dname" value="技术部">property>
          bean>
          <bean id="dept" class="com.syy.spring5.Dept">bean>
      
  4. xml注入集合属性

​ 4.1 注入数组类型属性

​ 4.2 注入List集合类型属性

​ 4.3 注入Map集合、set集合类型属性

​ ①创建类,定义数组、list、map、set类型属性,生成对应set方法

public class Stu {
    //1.数组类型属性
    private String[] courses;
    //2.list集合类型属性
    private List<String> list;
    //3.map集合类型属性
    private Map<String,String> maps;
    //4.set集合类型
    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;
    }
}

​ ②在Spring配置文件中进行配置


    <bean id="stu" class="com.syy.spring5.collectiontype.Stu">
        
        <property name="courses">
            <array>
                <value>java课程value>
                <value>spring课程value>
            array>
        property>
        
        <property name="list">
            <list>
                <value>张三value>
                <value>李四value>
            list>
        property>
        
        <property name="maps">
            <map>
                <entry key="Java" value="java">entry>
                <entry key="Spring" value="Spring">entry>
            map>
        property>
        
        <property name="sets">
            <set>
                <value>Mysqlvalue>
                <value>Redisvalue>
            set>
        property>
    bean>

​ 4.4 在集合中设置对象类型值

​ ①创建多个course对象

<bean id="course1" class="com.syy.spring5.collectiontype.Courses">
        <property name="cname" value="Spring框架">property>
    bean>
    <bean id="course2" class="com.syy.spring5.collectiontype.Courses">
        <property name="cname" value="Mybatis框架">property>
    bean>
    <bean id="course3" class="com.syy.spring5.collectiontype.Courses">
        <property name="cname" value="SpringMVC框架">property>
    bean>

​ ②在Stu对象中注入list集合类型,值为对象

 <property name="coursesList">
            <list>
                <ref bean="course1">ref>
                <ref bean="course2">ref>
                <ref bean="course3">ref>
            list>
        property>

ref中的bean值为courses对象的id值

​ 4.5 把集合注入部分提取出来

​ ①在Spring配置文件中引入名称空间util


<beans ...
       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">

​ ②使用util标签完成list集合注入提取

   
    <util:list id="booklist">
        <value>易筋经value>
        <value>九阳神经value>
        <value>一指禅value>
    util:list>
    
    <bean id="book" class="com.syy.spring5.collectiontype.Book">
        <property name="list" ref="booklist">property>
    bean>

(3) FactotyBean – 内置bean
  • Spring有两种类型,一种普通bean,另外一种工厂bean(FactoryBean)

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

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

      • 第一步,创建类,让这个类作为工厂bean,实现接口FactoryBean
      • 第二步,实现接口中的方法,在实现的方法中定义返回的bean类型
      public class MyBean implements FactoryBean<Courses> {
          //定义返回bean
          @Override
          public Courses getObject() throws Exception {
              Courses courses = new Courses();
              courses.setCname("abc");
              return courses;
          }
          @Override
          public Class<?> getObjectType() {
              return null;
          }
          @Override
          public boolean isSingleton() {
              return false;
          }
      }
      

      配置文件中:

       <bean id="myBean" class="com.syy.spring5.factorybean.MyBean">bean>
      

      测试类代码:

      @Test
          public void test3() {
              ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
              Courses course = context.getBean("myBean", Courses.class);
              System.out.println(course);
          }
      
(4) bean作用域
  • 在Spring中,设置创建bean实例是单实例还是多实例
  • 在Spring中,默认情况下,bean是单实例对象 – 验证实例地址值是否相同
  • 测试方法类:
    @Test
    public void test2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
       Book book1 = context.getBean("book", Book.class);
        Book book2 = context.getBean("book", Book.class);
        System.out.println(book1);
        System.out.println(book2);
    }
com.syy.spring5.collectiontype.Book@2f8f5f62
com.syy.spring5.collectiontype.Book@2f8f5f62 – 结果相同,默认为单实例
  • 如何设置单实例还是多实例

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

    • scope 属性值:

      • 默认值, singleton ,表示是单实例对象
      • prototype ,表示是多实例对象
    • <bean id="book" class="com.syy.spring5.collectiontype.Book" scope="prototype">
           <property name="list" ref="booklist">property>
           <property name="coursesList" ref="courseslist">property>
       bean>
      
    • com.syy.spring5.collectiontype.Book@1068e947
      com.syy.spring5.collectiontype.Book@7dc222ae – 结果不同,创建实例为多实例
    • singleton 和 prototype 的区别:

      • singleton 为单实例 , prototype 为多实例
      • 设置scope值为singleton 时,加载Spring配置文件时就会创建单实例对象
      • 设置scope值为 prototype 时,不是在加载Spring配置文件时创建对象,而是在调用getBean方法时创建多实例对象
(5) bean生命周期
  • 生命周期:从对象创建到对象销毁

  • bean的生命周期:

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

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

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

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

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

  • 演示bean生命周期

  • public class Orders {
        //无参数构造
        public Orders() {
            System.out.println("第一步 执行无参数构造创建bean实例");
        }
        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("第五步 执行销毁的方法");
        }
    }
    
    
  • 配置文件:

  • <bean id="orders" class="com.syy.spring5.factorybean.Orders" init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="李四">property>
    bean>
    
  • 测试类代码:

  • @Test
     public void test4(){
    //        ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
            //注意:ApplicationContext没有close方法,需要使用子接口
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
            Orders orders= context.getBean("orders",Orders.class);
            System.out.println("第四步 获取创建bean实例对象");
            System.out.println(orders);
            //手动让bean实例销毁
            context.close();
        }
    
  • 输出结果:

  • 第一步 执行无参数构造创建bean实例
    第二步 调用set方法设置属性值
    第三步 执行初始化的方法
    第四步 获取创建bean实例对象
    Orders{oname=‘李四’}
    第五步 执行销毁的方法

  • bean的后置处理器,bean的生命周期有七步

    1. 通过构造器创建bean实例(无参数构造)
    2. 为bean的属性设置值和对其他bean引用(调用set方法)
    3. 把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization – 可以定制一些在初始化之前的业务
    4. 调用bean的初始化的方法(需要进行配置初始化的方法)
    5. 把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization – 可以定制一些在初始化之前的业务
    6. bean可以使用了(对象获取到了)
    7. 当容器关闭时,调用bean的销毁的方法(需要进行配置销毁的方法)
  • 演示添加后置管理器效果

    • 创建类,实现接口BeanPostProcessor,创建后置处理器(会对所有bean实例添加后置管理器)

    • 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;
          }
      }
      
    • 配置文件中,配置后置管理器

    • <bean id="orders" class="com.syy.spring5.factorybean.Orders" init-method="initMethod" destroy-method="destroyMethod">
          <property name="oname" value="李四">property>
      bean>
          <bean id="myBeanPost" class="com.syy.spring5.factorybean.MyBeanPost">bean>
      
    • 测试结果:

    • 第一步 执行无参数构造创建bean实例
      第二步 调用set方法设置属性值
      在初始化之前的方法
      第三步 执行初始化的方法
      在初始化之后的方法
      第四步 获取创建bean实例对象
      Orders{oname=‘李四’}
      第五步 执行销毁的方法
(6) xml自动装配 – 不常用,实际中一般使用注解
  1. 自动装配:根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入

  2. 实现自动装配过程 – bean标签属性 autowire,配置自动装配

    1. 根据属性名称自动注入 – byName ,注入值bean的id值和类属性名称一样

          <bean id="emp" class="com.syy.spring5.autowire.Emp" autowire="byName">bean>
      
    2. 根据属性类型自动注入 – byType

      不能定义多个bean,

      <bean id="emp" class="com.syy.spring5.autowire.Emp" autowire="byType">bean>
      
(7) 管理外部属性文件
  • 引入外部属性文件配置数据库连接池

    • 配置德鲁伊连接池,引入德鲁伊连接池依赖jar包

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

    • #建议使用prop.名字的形式,以保证不会冲突
      prop.driverClass=com.mysql.jdbc.Driver
      prop.url=jdbc:mysql://localhost:13306/userdb
      prop.userName=root
      prop.password=root
      
    • 把外部properties属性文件引入到spring配置文件中

      • 引入context名称空间

      • xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="...
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
        
      • 在spring配置文件使用标签引入外部属性文件

      •     
            <context:property-placeholder location="classpath: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>
        
5.IOC *** 作Bean管理(基于注解)
  • 注解:

    • 注解是代码特殊标记,格式:@注解名称(属性名称 = 属性值,属性名称 = 属性值…)
    • 使用注解,注解作用在类上面,方法上面,属性上面
    • 使用注解的目的:简化xml配置
  • Spring针对Bean管理中创建对象提供注解

    • @Component --> 普通类中
    • @Service --> 业务逻辑层/service层
    • @Controller --> web层
    • @Repository --> DAO层/持久层
    • 上面四个注解功能是一样的,都可以用来创建bean实例
  • 基于注解方式实现对象创建

    • 第一步,映入依赖

    • 第二步,开启组件扫描 – 不开启,Spring无法找到类

      • 
          <context:component-scan base-package="com.syy">context:component-scan>
        
      • 使用组件扫描Spring就会知道是使用注解方式,就会在包下扫描所有文件,找到有注解的文件,创建对象

    • 第三步,创建类,在类上面添加创建对象注解

    • value属性值可以省略不写

    • 默认值是类名称,首字母小写

    • @Service(value = "userService")  //等于
      public class UserService {
          public void  add(){
              System.out.println("service add.......");
          }
      }
      
  • 开启组件扫描细节配置 – 可以设置扫描哪些内容

    • 示例一:

    • use-default-filters=“false” 表示现在不使用默认 filter,自己配置 filter
      context:include-filter ,设置扫描哪些内容

      • 
        <context:component-scan base-package="com.atguigu" use-defaultfilters="false">
        <context:include-filter type="annotation"
        expression="org.springframework.stereotype.Controller"/>
        
        context:component-scan>
        
    • 示例二:

    • context:exclude-filter: 设置哪些内容不进行扫描

      • <context:component-scan base-package="com.atguigu">
        <context:exclude-filter type="annotation"
        expression="org.springframework.stereotype.Controller"/>
        context:component-scan>
        
        
  • 基于注解方式实现属性注入

    • @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.......");
            }
        }
        
        
    • @Qualifier : 根据名称注入

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

      • @Service
        public class UserService {
            @Autowired
            @Qualifier(value = "userDaoImpl")
            //一个接口可能会有多个实现类,通过名称可以指定是哪个实现类
            private UserDao userDao;
            public void  add(){
                System.out.println("service add.......");
            }
        }
        
    • @Resource : 可以根据类型注入,可以根据名称注入

      • @Resource(name = "userDaoImpl")
            private UserDao userDao;
        
    • @Value : 注入普通类型

      • @Value(value = "李四")
           private String name;
        
  • 完全注解开发

    • 创建配置类,替代xml配置文件

      @Configuration
      @ComponentScan(basePackages = {"com.syy"})
      public class SpringConfig {
      
      
    • 编写测试类

      @Test
      public void test2(){
              ApplicationContext context =
                      new AnnotationConfigApplicationContext(SpringConfig.class);
          // ApplicationContext context =new ClassPathXmlApplicationContext("bean2.xml");
              UserService userService = context.getBean("userService",UserService.class);
              System.out.println(userService);
              userService.add();
          }
      
三、Aop 1.AOP概念

AOP : 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而是的业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率.

通俗描述 : 不通过修改源代码方式,在主干功能里面添加新功能

2.AOP底层使用动态代理

两种情况:

第一种,有接口情况,使用 JDK 动态代理 - 创建接口的实现类代理对象,增强类的方法

第二种,没有接口情况,使用 CGLIB 动态代理 - 创建子类的代理对象,增强类的方法

3.AOP术语
  • 连接点 - 类里面哪些方法可以被增强,这些方法称为连接点
  • 切入点 - 实际被真正增强的方法,称为切入点
  • 通知(增强) - 实际增强的逻辑部分称为通知(增强)
    • 通知有多种类型:
      • 前置通知 - 方法之前执行 - @Before
      • 后置通知 - 方法之后执行 - @AfterReturning
        • 在方法之后执行,有异常不执行
      • 环绕通知 - 方法前后都执行 - @Around
      • 异常通知 - 出现了异常后执行 - @AfterThrowing
      • 最终通知 - 类似于try,catch中finally中的代码 - @After
        • 在方法之后执行,不管有没有异常都执行
  • 切面 - 是动作,把通知应用到切入点过程
4.AOP *** 作准备工作 (1) Spring框架一般都是基于AspectJ实现AOP *** 作
  • AspectJ不是Spring组成部分,是独立的AOP框架,一般把AspectJ和Spring框架一起使用,进行AOp *** 作
(2) 基于AspectJ实现AOP *** 作
  • 基于xml配置文件实现
  • 基于注解方式实现(常用)
(3) 切入点表达式
  • 切入点表达式作用:知道对哪个类里面的哪个方法进行增强
  • 语法结构:execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])
  • 举例:
    • 对 com.atguigu.dao.BookDao 类里面的 add 进行增强
      • execution(* com.atguigu.dao.BookDao.add(…))
    • 对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
      • execution(* com.atguigu.dao.BookDao.* (…))
    • 对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强
      • execution(* com.atguigu.dao.. (…))
5.AOP *** 作 - AspectJ注解 (1) 创建类,在类中定义方法
public class User {
    public void add(){
        System.out.println("未增强代码add..");
    }
}
(2) 创建增强类(编写增强逻辑)
public class UserProxy {
    public void before(){
        System.out.println("前置通知方法add....");
    }
}

(3) 进行通知的配置
  • 引入context和aop的名称空间,开启注解扫描和开启代理对象

<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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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.syy.spring5">context:component-scan>
    
    <aop:aspectj-autoproxy>aop:aspectj-autoproxy>
beans>
  • 使用注解创建对象
@Component
public class User {...}
@Component
public class UserProxy {...}
  • 在增强类上添加注解 @AspectJ
@Component
@Aspect
public class UserProxy {...}
(4) 配置不同类型的通知
@Component
@Aspect
public class UserProxy {
    @Before(value = "execution(* com.syy.spring5.dao.User.add(..))")
    public void before() {
        System.out.println("前置通知方法add....");
    }
@AfterReturning(value = "execution(* com.syy.spring5.dao.User.add(..)))")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }

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

    //异常通知
    @AfterThrowing(value = "execution(* com.syy.spring5.dao.User.add(..))")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }

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

(5)相同的切入点抽取

创建一个方法进行相同切入点的抽取,通知方法在value中调用方法

    @Pointcut(value = "execution(* com.syy.spring5.dao.User.add(..))")
    public void pointdemo(){
    }
    @Before(value = "pointdemo()")
    public void before() {
        System.out.println("前置通知方法add....");
    }

(6) 设置增强类的优先级

当有多个增强类对同一个方法进行增强时,可以在增强类上添加注解 @Order(数字类型值),数字类型值越小优先级越高

@Component
@Aspect
@Order(1)
public class UserProxy {...}
(7) 完全注解开发

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

@Configuration
@ComponentScan(basePackages = {"com.syy"})
@EnableAspectJAutoProxy(proxyTargetClass = true)//替代  
public class ConfigAop {...}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/727279.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存