Spring面向切面编程AOP(around)实战

spring aop的环绕通知around功能强大,我们这里就不细说,直接上代码,看着注释就能明白

需要的可以点击下载源码

1.如果使用注解的方式则需要先创建个注解类

package com.mb.aop;

import java.lang.annotation.*;

/**
 * 常用注解说明:
     * 1. RetentionPolicy(保留策略)是一个enum类型,有三个值
         * SOURCE        --  这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译后,Annotation的数据就会消失,并不会保留在编译好的.class文件里
         * CLASS         --  这个Annotation类型的信息保留在程序源码中,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信息加载到虚拟 机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS。
         * RUNTIME       --  在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的。
         *
     * 2.ElementType @Target中的ElementType用来指定Annotation类型可以用在哪些元素上
         * TYPE(类型)    -- 在Class,Interface,Enum和Annotation类型上
         * FIELD        -- 属性上
         * METHOD       -- 方法上
         * PARAMETER    -- 参数上
         * CONSTRUCTOR  -- 构造函数上
         * LOCAL_VARIABLE -- 局部变量
         * ANNOTATION_TYPE   -- Annotation类型上
         * PACKAGE           -- 包上
         *
      * 3.Documented    -- 让这个Annotation类型的信息能够显示在API说明文档上;没有添加的话,使用javadoc生成的API文件找不到这个类型生成的信息
 */

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AssertOK {

    String isLogin() default "false";

}

2.再创建个拦截器,拦截目标方法并在目标方法前后执行操作

package com.mb.aop;
import com.sun.istack.internal.logging.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.TypeVariable;

@Component
@Aspect
public class AssertOKAspectj {

    private Logger logger = Logger.getLogger(this.getClass());

    @Pointcut("@annotation(com.mb.aop.AssertOK)")  //表示所有带有AssertOK的注解
    public void point(){

    }

//    @Pointcut("execution(* com.mb..*.*(..))")  //表示拦截所有com.mb包及子包下的所有的方法
//    public void point(){
//
//    }

    @Around(value = "point()")
    public Object assertAround(ProceedingJoinPoint pjp){

        //判断注解标识如果不为false则,进行登录
        Class<?> aClass = pjp.getTarget().getClass(); //先获取被织入增强处理的目标对象,再获取目标类的clazz
        String methodName = pjp.getSignature().getName(); //先获取目标方法的签名,再获取目标方法的名
        logger.info("methodName: "+methodName);  // 输出目标方法名
        Class[] parameterTypes = ((MethodSignature) pjp.getSignature()).getParameterTypes(); //获取目标方法参数类型
        Object[] args = pjp.getArgs();  //获取目标方法的入参
        for (int i = 0; i < args.length; i++) {
            logger.info("argsName: "+args[i]); //输出目标方法的参数
        }
        try {
            Method method = aClass.getMethod(methodName, parameterTypes);  //获取目标方法
            AssertOK annotation = method.getAnnotation(AssertOK.class);  //获取方法上的注解
            annotation.isLogin();  //获取注解函数值
            long starttime = System.currentTimeMillis();
            Object proceed = pjp.proceed();  //执行目标方法
            long exctime = System.currentTimeMillis() - starttime;
            logger.info("执行时间:"+exctime + "毫秒");
            logger.info("proceed: "+proceed);  //打印目标方法的return结果
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return "aop的返回值";
    }

}

3.这里为了多场景验证,我创建了2个目标类分别是:Login 、QueryAccount

package com.mb.request;

import com.mb.aop.AssertOK;
import org.springframework.stereotype.Component;

@Component
public class Login {

    @AssertOK(isLogin = "ture")
    public String login(String username,String password){
        System.out.println(username+" 登录成功 "+", 登录的密码是 "+password);
        return "登录成功";
    }

    @AssertOK(isLogin = "false")
    public String loginOnline(String name,String pwd){
        String login = login(name, pwd);
        System.out.println("login 的返回值:"+login);
        return "loginOnline 成功";
    }
}
package com.mb.request;

import com.mb.aop.AssertOK;
import org.springframework.stereotype.Component;

@Component
public class QueryAccount {

    @AssertOK
    public String queryAccount(){

        System.out.println("账户查询成功....");
        return "success";
    }
}

4.配置spring包扫描和自动代码配置,这里默认使用的是jdk动态代理

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

    <!-- 自动扫描web包 ,将带有注解的类 纳入spring容器管理 -->
    <context:component-scan base-package="com.mb"></context:component-scan>

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

5.最后就是需要我们把pom.xml文件中添加aspectj和spring核心包等

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mb</groupId>
    <artifactId>aspectjdemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.20.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.1</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.3.7.RELEASE</version>
        <scope>test</scope>
    </dependency>
</dependencies>
</project>

6.以上搞定,下面我们来做测试,验证配置的aop是否生效

package com.mb.request;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:**/applicationContext*.xml"})
public class RequestTest {

    @Autowired
    Login login;
    @Autowired
    QueryAccount queryAccount;

    @Test
    public void loginTest(){
        login.loginOnline("米小圈","123456");
    }
}

7.测试结果:

二月 27, 2019 12:04:01 上午 [com.mb.aop.AssertOKAspectj]  invoke0
信息: methodName: loginOnline
二月 27, 2019 12:04:01 上午 [com.mb.aop.AssertOKAspectj]  invoke0
信息: argsName: 米小圈
二月 27, 2019 12:04:01 上午 [com.mb.aop.AssertOKAspectj]  invoke0
信息: argsName: 123456
米小圈 登录成功 , 登录的密码是 123456
login 的返回值:登录成功
二月 27, 2019 12:04:01 上午 [com.mb.aop.AssertOKAspectj]  invoke0
信息: 执行时间:15毫秒
二月 27, 2019 12:04:01 上午 [com.mb.aop.AssertOKAspectj]  invoke0
信息: proceed: loginOnline 成功

原文地址:https://www.cnblogs.com/unknows/p/10441164.html

时间: 2024-10-15 12:44:16

Spring面向切面编程AOP(around)实战的相关文章

Spring面向切面编程(AOP)

1 spring容器中bean特性 Spring容器的javabean对象默认是单例的. 通过在xml文件中,配置可以使用某些对象为多列. Spring容器中的javabean对象默认是立即加载(立即实例化:spring加载完成,立即创建对象) scope:属性 singleton:默认值为单例,默认也是立即加载,在加载完成spring容器的时候,bean对象已经创建完成 prototype:多例的,默认懒加载,spring容器加载完成的时候,不会创建bean的对象,只有从容器获得bean对象的

Spring面向切面编程(AOP,Aspect&#160;Oriented&#160;Programming)

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术.主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等.使用JDK的动态代理可以实现AOP. AOP通过代理的方式都程序动态统一添加功能 现在要给功能4增加一些额外的行为,如处理日志,处理权限等,可以使用代理实现.我们在功能4外面包装一个对象,假设叫A, model原来是直接调用功能4,

Spring之面向切面编程AOP(二)

简介 当积累的知识点到一定量的时候,学新知识就变得容易多了.希望再接下来的学习顺利进行下去.今天知识也是挺简单的,主要就是AOP面向切面编程.其中牵涉到了JDKProxy和CGLIB两个代理类,如何使用好,加以深刻理解.学起Spring切面编程也就简单多了 代理模式 1. 代理模式介绍 代理模式的英文叫做Proxy或Surrogate,中文都可译为"代理",所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对

Spring(四):面向切面编程AOP

横切关注点:分布于应用中多处的功能 面向切面编程AOP:将横切关注点与业务逻辑相分离 在使用面向切面编程时,仍在一个地方定义通用功能,但是可以通过声明的方式定义这个功能以何种方式在何处应用,而无需修改受影响的类. 横切关注点可以被模块化为特殊的类,这些类被称为切面. 好处: 每个关注点集中于一处,而不是分散到多处代码中 服务模块更加简洁,因为它们只包含主要关注点的代码,次要关注点被转移到切面中了 1.定义AOP术语 1.1.通知(Advice) 切面的工作被称为通知. 通知定义了切面是什么以及何

Spring面向切面编程(二)简单AOP实例

简单实现一个用户登陆的功能,在用户登陆之前进行日志打印,用户登陆之后进行登陆成功日志打印. Maven添加Spring jar spring面向切面编程(一)AOP术语 添加Spring AOP的jar 参考:Maven添加Spring jar 还需添加: 创建User类: package com.user; public class User { private String username; private String password; public String getUsernam

spring中面向切面编程(AOP)的个人理解

面向切面编程AOP,是spring的一大特点 Aspect切面:封装共性功能的(增强功能的)类 Advice通过:切面类中封装的增强功能的方法. PointCut:切入点,是一个集合的概念,该集合的表达使用一个正则表达式表达 所有核心业务对象的所有方法的前后(事务处理AOP典型的应用) JoinPoint:连接点,程序中需要加入advice的地方,而且正在执行的ponitCut 织入(Weaving):将aspect和核心业务对象,进行整合的过程. 通过特定接口实现AOp Aop通知的类型: B

Spring 面向切面编程(AOP)

Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of Control – IOC) 理解依赖注入(DI – Dependency Injection) Bean XML 配置(1)- 通过XML配置加载Bean Bean XML 配置(2)- Bean作用域与生命周期回调方法配置 Bean XML 配置(3)- 依赖注入配置 Bean XML 配置(

Spring面向切面编程

  1.面向切面编程(AOP)的概念:把项目中需要在多处用到的功能,比如日志.安全和事物等集中到一个类中处理,而不用在每个需要用到该功能的地方显式调用.   2.术语解释:        横切关注点:分布应用于多处的功能        切面:横切关注点可以被模块化为一个类,这个类被称为一个切面        通知(advice):切面要完成的工作.Spring的通知有5种类型:before.after.after-returning.after-throwing和around这五种类型.    

Web项目中静态代理和动态代理为基础的面向切面编程AOP

本来每天更新的,我一般喜欢夜里过了十二点的时候发文章,结果难道是愚人节吗?学校的网也很有意思,断了,把我给耍了...好吧-开始今天的话题AOP.AOP太重要了,所以放到第二篇文章来谈这个话题,AOP是Spring中的重要概念.如果这个不理解Web开发中的三大框架的原理,那就呵呵了.时常听到同学和网友议论Web程序员大部分时间都是在考皮XML配置,我当时听到也是醉了,所以我要用心学习Web,其实这里面蕴含的设计模式.算法.架构思想在源码中体现的淋漓尽致啊,一个大宝库竟然视而不见可惜了.下面就一起品