• 【Spring框架学习】AOP机制 配置文件式 详解


    Youzg Logo

    首先是 applicationContext.xml(核心配置文件):

    配置文件:

    首先,我们需要在配置文件的头部,beans标签的属性中 加上aop命名空间:

    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
             https://www.springframework.org/schema/aop/spring-aop.xsd"
    

    仅加入aop命名空间后,配置文件内容如下:

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

    那么,配置文件式 也存在着两种使用方式,本人在这里一一来讲解下:

    方式一 —— 原生 spring API接口:

    配置文件 语法:

    beans标签内,增加如下子级标签导入aop约束

    <aop:config>
    	<!--aop配置内容-->
    </aop:config>
    

    在config标签内部,配置aop的内容:
    config配置内容,总共分为三类:

    配置内容 分类:

    1. 用于配置切面

    在第二种使用方式中会进行讲解:

    <aop:aspect/>
    
    1. 用于配置切入点
    <aop:pointcut id="切入点id" expression="execution(表达式)"/>
    

    现在,本人来讲解下 上述表达式的语法
    表达式语法

    权限名 返回值类型 类的全路径名.目标方法名(参数全路径类型1, 参数全路径类型2 ...)
    

    那么,我们在使用的时候也可以对其进行简化:
    简化:

    • 权限名可以省略
    • 返回值可以设置为 '*',表示任意返回值都能匹配上
    • 包名可以用'.'代替,表示其父包下的所有子包都能匹配上
    • 类名/方法名 可以设置为'*',表示 其父包下的所有类/其所属类中的所有方法 都能匹配上
    • 参数可以用'. .'代替,表示任意个数、任意种类的参数都能被匹配上
    1. 用于为切入点配置拦截器
    <aop:advisor advice-ref="横切关注点的bean id" pointcut="切入点 id" />
    

    那么,我们该如何去定义一个拦截器呢?

    定义拦截器 语法:

    首先,我们需要写一个类,继承如下四个几口中的一个:

    MethodBeforeAdvice接口 —— 提供前置拦截方法:

    参数

    • method:
      被拦截的方法(即:切入点)
    • objects:
      执行该方法的参数
    • Object o:
      执行该方法的代理对象

    AfterReturningAdvice接口 —— 提供最终拦截方法:

    参数

    • returnValue:
      目标方法(即:切入点)的返回值
    • method:
      目标方法(即:切入点)
    • args:
      目标方法(即:切入点)的参数
    • target:
      执行该方法的代理对象

    MethodInterceptor接口 —— 提供环绕拦截方法:

    提供 public Object invoke(MethodInvocation invocation) throws Throwable 方法
    参数类型MethodInvocation,主要是用于 获取 目标对象 以及 方法信息


    ThrowsAdvice接口 —— 提供异常抛出拦截方法

    无需要重写的方法


    那么,现在本人就来展示下方式一的使用:

    使用展示:

    首先,本人给出一个dao层实现类:

    package edu.youzg.about_aop.test.dao;
    
    import org.springframework.stereotype.Repository;
    
    /**
     * @Author: Youzg
     * @CreateTime: 2020-05-01 20:31
     * @Description:带你深究Java的本质!
     */
    @Repository
    public class UserDaoImpl implements IUserDao {
    
        @Override
        public void add() {
            System.out.println("dao层add方法被调用!");
        }
    
        @Override
        public void delete() {
            System.out.println("dao层delete方法被调用!");
        }
    
        @Override
        public void alter() {
            System.out.println("dao层alter方法被调用!");
        }
    
        @Override
        public void select() {
            System.out.println("dao层select方法被调用!");
        }
    
    }
    

    接下来,本人来给出一个service层的实现类:

    package edu.youzg.about_aop.test.service;
    
    import edu.youzg.about_aop.test.dao.IUserDao;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @Author: Youzg
     * @CreateTime: 2020-05-01 20:33
     * @Description:带你深究Java的本质!
     */
    @Service
    public class UserServiceImpl implements IUserService {
        @Autowired
        private IUserDao userDao;
    
        @Override
        public void login() {
            System.out.println("service层login方法执行!");
            userDao.select();
        }
    
        @Override
        public void register() {
            System.out.println("service层register方法执行!");
            userDao.add();
        }
    
        @Override
        public void rename() {
            System.out.println("service层rename方法执行!");
            userDao.alter();
        }
    
        @Override
        public void cancellat() {
            System.out.println("service层cancellat方法执行!");
            userDao.delete();
        }
    
    }
    

    现在,本人来给出一个通知器类:

    package edu.youzg.about_aop.test.aspect;
    
    import org.springframework.aop.MethodBeforeAdvice;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    @Component	//将其注入IoC容器中
    public class MyAspect implements MethodBeforeAdvice {	//继承Adice接口,实现其自带方法,成为一个拦截器(通知器)
    
        @Override
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println("===== Youzg代理执行 之 前置增强 =====");
        }
    
    }
    

    最后,现在本人 来给出配置文件:

    <?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"
           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
             https://www.springframework.org/schema/context/spring-context.xsd
             http://www.springframework.org/schema/aop
             https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <context:component-scan base-package="edu.youzg.about_aop" />
        
        <aop:config>
            <!-- 定义拦截器 -->
            <aop:advisor advice-ref="myAspect" pointcut="execution(* edu.youzg.about_aop..*.*(..))" />
        </aop:config>
    
    </beans>
    

    最后,本人再来给出一个测试类

    package edu.youzg.about_aop.test;
    
    import edu.youzg.about_aop.test.service.IUserService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @Author: Youzg
     * @CreateTime: 2020-05-01 23:11
     * @Description:带你深究Java的本质!
     */
    public class Test {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            IUserService userService = context.getBean("userServiceImpl", IUserService.class);
            userService.login();
        }
        
    }
    

    那么,现在本人来展示下运行结果:
    运行结果 展示


    方式二 —— 自定义类实现AOP机制:

    方式二的通知有五个类型:

    分类:

    • 前置通知
    • 后置通知
    • 最终通知
    • 环绕通知
    • 异常通知

    格式:

    首先得配置一个自定义拦截器类:

    接下来是配置文件:

    配置文件:

    <aop:config>
        <aop:aspect  id="切面bean id" ref="切面">
            <!--切入点-->
            <aop:pointcut id="自定义拦截器 bean id" expression="execution(表达式)"/>
            <!--五种通知类型-->
            <!--前置通知-->
            <aop:before method="前置拦截方法名"  pointcut-ref="切入点id"  />
            <!--最终通知-->
            <aop:after-returning method="最终拦截方法名" pointcut-ref="切入点id" />
            <!--后置通知-->
            <aop:after method="后置拦截方法名" pointcut-ref="切入点id" />
            <!--环绕通知-->
            <aop:around method="环绕拦截方法名" pointcut-ref="切入点id" />
            <!--异常通知-->
            <aop:after-throwing method="异常拦截方法名" pointcut-ref="切入点id" />
        </aop:aspect>
    </aop:config>
    

    为了方便,在上文中,本人将所有通知方式都在一起展示了
    那么,我们在使用的时候,只需要针对需求选取其中几种就行


    那么,现在本人来展示下方式二的使用:

    使用展示:

    首先,本人来给出一个自定义拦截器类:

    package edu.youzg.about_aop.test.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.springframework.stereotype.Component;
    
    /**
     * @Author: Youzg
     * @CreateTime: 2020-05-01 21:56
     * @Description:带你深究Java的本质!
     */
    @Component
    public class YouzgAspect {
    
        public void myBefore() {
            System.out.println("==before拦截执行==");
        }
    
        public void myAfter() {
            System.out.println("==after拦截执行==");
        }
    
        public void myAfterReturning() {
            System.out.println("==afterReturning拦截执行==");
        }
    
        public void myThrowing() {
            System.out.println("==throwing拦截执行==");
        }
    
        public Object myAround(ProceedingJoinPoint pjp) {
            Object result = null;
            try {
                System.out.println("== around拦截执行 ==");
                result = pjp.proceed();
                // 方法执行完毕之后编写
                System.out.println("== around拦截完毕 ==");
                System.out.println("==方法执行的结果[" + result + "]==");
            }catch(Throwable t){
            // 可以处理,异常通知
                System.out.println("异常处理");
            }
            return result;
        }
    
    }
    

    现在,本人来给出配置文件的信息:

    <?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"
           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
             https://www.springframework.org/schema/context/spring-context.xsd
             http://www.springframework.org/schema/aop
             https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <context:component-scan base-package="edu.youzg.about_aop" />
    
        <aop:config>
            <aop:aspect id="youzgAsp" ref="youzgAspect">
                <!--切入点-->
                <aop:pointcut id="youzgPoingcut" expression="execution(* edu.youzg.about_aop..*.*(..))"/>
                <!--五种通知类型-->
                <!--前置通知-->
                <aop:before method="myBefore" pointcut-ref="youzgPoingcut" />
                <!--后置通知-->
                <aop:after-returning method="myAfterReturning" pointcut-ref="youzgPoingcut" />
                <!--最终通知-->
                <aop:after method="myAfter" pointcut-ref="youzgPoingcut" />
                <!--环绕通知-->
                <aop:around method="myAround" pointcut-ref="youzgPoingcut" />
                <!--异常通知-->
                <aop:after-throwing method="myThrowing" pointcut-ref="youzgPoingcut" />
            </aop:aspect>
        </aop:config>
    
    </beans>
    

    最后,本人再来给出一个测试类

    package edu.youzg.about_aop.test;
    
    import edu.youzg.about_aop.test.service.IUserService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @Author: Youzg
     * @CreateTime: 2020-05-01 23:11
     * @Description:带你深究Java的本质!
     */
    public class Test {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            IUserService userService = context.getBean("userServiceImpl", IUserService.class);
            userService.login();
        }
        
    }
    

    那么,现在本人来展示下运行结果:运行结果 展示


  • 相关阅读:
    C# 依赖注入中的 控制反转(Assembly)实现
    C# 依赖注入中的 控制反转(Assembly)实现
    Asp.net web form 动态生成控件的注意事项
    jackson的转换object转map
    SpringCloud+Feign+Hystrix使用FallbackFactory统一处理,查看服务调用异常或失败,进入熔断降级处理的原因
    feign调用返回object类型转换成实体
    Springboot @ResponseBody返回中文乱码
    Feign 传参问题及传输Date类型参数的时差 坑
    Mybatis plus条件构造器QueryWrapper的简单用法
    Java命令里面的EQ、NE、GT、LT、GE、LE分别代表含义
  • 原文地址:https://www.cnblogs.com/codderYouzg/p/12815324.html
Copyright © 2020-2023  润新知