springAop后置通知 AfterReturningAdvice实现原理和代码案例

Aop原理

SpringAop 原理就是动态代理

对于实现接口的目标类使用的是jdk动态代理

对于没有实现任何接口的目标类,使用的是cglib的动态代理

代理类是程序在运行期间由JVM根据反射等机制动态生成的自动生成代理类和代理对象。

所谓动态就是指在程序运行前不存在代理类的字节码文件。

SpringAop的配置方式

三种配置方式

一:SpringAop1.x 使用ProxyFactoryBean手动埃利

二:SpringAop2.x 基于命名控件的配置

三:Annotation 基于注解的配置(推荐)

Advice类型

SpringAop支持五种类型的通知(增强)
在这里插入图片描述
注意:多个Advice之间不允许有耦合,即多个Advice之间不允许有业务交叉。

(1):SpringAop1.x 使用ProxyFactoryBean 手动代理

配置方式:

基本用法: 添加jar包

<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!--ioc01-core-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
        <!--ioc01-bean-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
        </dependency>
        <!--ioc01-context-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <!--ioc01-expression-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
        </dependency>
        <!--Aop依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <!--cglib技术-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
        </dependency>

书写UserService接口

package springaop03.service;


/**
 * package_name:springaop01.service
 *
 * author:徐亚远 Date:2020/2/18 18:29
 * 项目名:springDemo01
 * Description:
 **/
public interface UserService {

    /**
     * @Author : 徐亚远
     * @Date : 2020/2/18 20:34
     * @param username
     * @param password
     * @Description :
     */
    void login(String username, String password);
}

书写实现UserService的实现类UserServiceImpl

package springaop03.service.impl;

import springaop03.service.UserService;

/**
 * package_name:springaop01.service.impl
 * Author:徐亚远
 * Date:2020/2/18 18:29
 * 项目名:springDemo01
 * Desription:
 **/
public class UserServlceImpl implements UserService {


    /**
     * @param password
     * @param username
     * @Author : 徐亚远
     * @Date : 2020/2/18 21:03
     * @Description :
     */

    @Override
    public void login(String username, String password) {
        System.out.println("loginUserServiceImpl登录方法执行:" + username + "    " + password);
    }
}

1:配置Advice通知

1定义增强类,实现相应的接口

package springaop03.advice;

import org.springframework.aop.AfterReturningAdvice;

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

/**
 * package_name:springaop03.advice
 *
 * @author:徐亚远 Date:2020/2/19 16:33
 * 项目名:springDemo01
 * Description:后置通知 在方法执行后添加功能
 * Version: 1.0
 **/

public class AfterAdvice implements AfterReturningAdvice {
    /**
     * Callback after a given method successfully returned.
     *
     * @param returnValue the value returned by the method, if any
     * @param method      method being invoked
     * @param args        arguments to the method
     * @param target      target of the method invocation. May be {@code null}.
     * @throws Throwable if this object wishes to abort the call.
     *                   Any exception thrown will be returned to the caller if it's
     *                   allowed by the method signature. Otherwise the exception
     *                   will be wrapped as a runtime exception.
     */
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("后置通知:"+method.getName()+" "+"start at:["+System.currentTimeMillis()+"]"+"" +
                "  "+"args:"+Arrays.toString(args)
                +"target:"+target+" "+"returnValue:"+returnValue);
    }
}

配置sping.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

配置spring.xml文件的
第一步 配置目标类实例

  <bean id="userServiceTarget" class="springaop03.service.impl.UserServlceImpl"/>

第二步 配置后置通知

<bean id="afterAdvice" class="springaop03.advice.AfterAdvice"/>

第三步 配置advisor

<bean id="afterAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <!-- 1 配置通知-->
        <property name="advice" ref="afterAdvice"/>
        <!-- 2 配置切点-->
        <property name="mappedNames">
            <list>
                <value>login</value>
            </list>
        </property>
    </bean>

第四步 配置代理

 <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 1 目标类实例-->
        <property name="target" ref="userServiceTarget"/>
        <!-- 2 目标类实例接口列表-->
        <property name="interfaces">
            <list>
                <value>springaop03.service.UserService</value>
            </list>
        </property>
        <!-- 3交叉业务-->
        <property name="interceptorNames">
            <list>
                <value>afterAdvisor</value>
            </list>
        </property>
    </bean>

完整的spring.xml配置文件如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--配置目标类实例-->
    <bean id="userServiceTarget" class="springaop03.service.impl.UserServlceImpl"/>

    <!--配置后置通知-->
    <bean id="afterAdvice" class="springaop03.advice.AfterAdvice"/>
    <!--配置advisor-->
    <bean id="afterAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
        <!--配置通知-->
        <property name="advice" ref="afterAdvice"/>
        <!--配置切点-->
        <property name="mappedNames">
            <list>
                <value>login</value>
            </list>
        </property>
    </bean>
<!--配置代理-->
    <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--目标类实例-->
        <property name="target" ref="userServiceTarget"/>
        <!--目标类实例接口列表-->
        <property name="interfaces">
            <list>
                <value>springaop03.service.UserService</value>
            </list>
        </property>
        <!--交叉业务-->
        <property name="interceptorNames">
            <list>
                <value>afterAdvisor</value>
            </list>
        </property>
    </bean>

</beans>

书写测试类

package springaop03.controller;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springaop03.service.UserService;

/**
 * package_name:springaop03.controller
 *
 * @author:徐亚远 Date:2020/2/19 13:06
 * 项目名:springDemo01
 * Description:TODO
 * Version: 1.0
 **/

public class AopOneController {
    public static void main(String [] args){
        ApplicationContext ac = new ClassPathXmlApplicationContext("/aop03/spring.xml");
    UserService userService = (UserService) ac.getBean("userService");
        //使用的是jdk的动态代理  class com.sun.proxy.$Proxy4
        System.out.println(userService.getClass());
        userService.login("admin","xu1230" );
    }
}

执行结果如图:
在这里插入图片描述

发布了64 篇原创文章 · 获赞 1 · 访问量 888

猜你喜欢

转载自blog.csdn.net/weixin_43311650/article/details/104397033