• 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 成功
  • 相关阅读:
    hdu 4503(湫湫系列故事——植树节)
    JAVA里面如何让一个线程死亡或结束
    c 语言static
    TUXEDO与ORACLE数据库的互连
    关于使用PRO*C编程的一些简单说明和例子
    atoi函数
    我的顶级Java工具名单
    Tuxedo动态配置命令 tmconfig用法总结
    main(argc,argv) 中的参数
    pro c中varchar类型变量的arr函数是做什么用?
  • 原文地址:https://www.cnblogs.com/unknows/p/10441164.html
Copyright © 2020-2023  润新知