zoukankan      html  css  js  c++  java
  • Spring课程 Spring入门篇 7-3 advice扩展

    课程链接:

    1    解析

    1.1  advice中aspect 切面传参

    1.2  通知参数名称——argNames属性, 参数为 JoinPoint、ProceedingJoinPoint、JoinPointStaticPart时,可以忽略argNames属性

    1.3  其余不重要的部分

    2    代码演练

    2.1  前置通知@before给advice传递参数

    2.1  前置通知@before传递类参数

    1    解析

     1.1  advice中aspect 切面传参

      String传参和类传参参照2.1和2.2

    泛型传参

    1.2  通知参数名称——argNames属性, 参数为 JoinPoint、ProceedingJoinPoint、JoinPointStaticPart时,可以忽略argNames属性

    1.3  其余不重要的部分

     

     Introductions
    ·允许一个切面声明一个通知对象实现指定接口,并且提供了一个接口实现类来代表这些对象
    ·introduction使用@DeclareParents进行注解,这个注解用来定义匹配的类型拥有一个新的parent

    2    代码演练

    2.1  前置通知@before给advice传递String参数

    切面类:

    package com.imooc.aop.aspectj;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    /**
     * 注解切面类
     * 注:本页面主要功能是:整理各种通知的注解
     * @author weijingli
     *
     */
    
    @Component
    @Aspect
    public class MoocAspect {
        
        /**
         * 该处设置切入点,主要是用来匹配目标对象类
         * 
         * 执行com.imooc.aop.aspect.biz 包下的 以Biz结尾的类的所有方法
         */
        @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")
        public void pointcut(){}
        
        
        /**
         * 执行com.imooc.aop.aspect.biz 包下的所有类的  所有方法
         */
        @Pointcut("within(com.imooc.aop.aspectj.biz.*)")
        public void bizPointcut(){}
        
        
        /**
         *     前置通知   样例1
         */
        @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")
        public void before(){
            System.out.println("before1");
        }
        
        /**
         * AfterReturning 执行后通知,接收  目标对象返回的值
         * @param reValue
         */
        @AfterReturning(pointcut="pointcut()",returning="reValue")
        public void afterReturning(Object reValue){
            System.out.println("AfterReturning:   "+reValue);
        }
        
        /**
         * 后置通知  相当于java语法中的finally
         */
        @After("pointcut()")
        public void after(){
            System.out.println("after:");
        }
        
        /**
         * 异常通知:
         * 
         * 接收异常返回的信息
         */
        @AfterThrowing(pointcut="pointcut()",throwing="e")
        public void afterThrowing(RuntimeException e){
            System.out.println("AfterThrowing: "+e.getMessage());
        }
        
        /**
         * 环绕通知:
         * @param pjp
         * @return
         * @throws Throwable
         */
        @Around("pointcut()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable{
            System.out.println("around 1");
            Object obj = pjp.proceed();
            System.out.println("around 2");
            System.out.println("around :"+obj);
            return obj;
        }
        
        
        /**
         *     前置通知   带参数
         */
        @Before("pointcut()&&args(arg)")
        public void beforeWithParam(String arg){
            System.out.println("beforeWithParam:"+arg);
        }
        
        
        
        
        /**
         *     前置通知   样例2
         */
        /*@Before("pointcut()")
        public void before2(){
            System.out.println("before2");
        }*/
        
    
        
    
    }

    实体类:

    package com.imooc.aop.aspectj.biz;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class MoocBiz {
        /**
         * 1    为什么 用 save方法 返回 String 类型?
         * 
         * 答:为了方便After Or AfterReturning 通知  接收  返回值
         * 
         * 2     为什么接收String 参数?
         * 
         * 答:只是为了方便测试,没有任何实际意义。
         * @param arg
         * @return
         */
        public String save(String arg){
            System.out.println("MoocBiz save "+arg);
    //        throw new RuntimeException("Save Failed!");
            return "Save Success!";
        }
    }

    配置文件:

    <?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:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    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"
     >
    
    
    <!-- 自己添加注意:
    1    context:component-scan 扫描包,根据注解找到通知。         使用注解的时候,记得添加扫描包的功能
    2    aop:aspectj-autoproxy 通过配置织入@Aspectj切面 -->
    
    <context:component-scan base-package="com.imooc.aop.aspectj"/>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    
     <bean id="moocBiz" class="com.imooc.aop.aspectj.biz.MoocBiz"></bean>
     
    </beans>

    测试类:

    package com.imooc.test.aop;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.BlockJUnit4ClassRunner;
    
    import com.imooc.aop.aspectj.biz.MoocBiz;
    import com.imooc.test.base.UnitTestBase;
    
    /**    @RunWith 是一个运行器 
     *     
     * @RunWith(JUnit4.class)就是指用JUnit4来运行       
     *    
     *@RunWith(Suite.class)的话就是一套测试集合
     *
     *@RunWith(Suite.class)的话就是一套测试集合                                                 
     *                                        
     *@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件                                                  
     * 
     * @author weijingli
     */
    @RunWith(BlockJUnit4ClassRunner.class)
    public class TestAspectJ extends UnitTestBase{
    
        public TestAspectJ() {
            super("classpath:spring-aop-aspectj.xml");
        }
        
        @Test
        public void testAspectJ(){
            MoocBiz mBiz = super.getbean("moocBiz");
            mBiz.save("This is Test!");
        }
        
    
    }

    打印日志:

    五月 02, 2019 2:28:44 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7fe219e7: startup date [Thu May 02 14:28:44 CST 2019]; root of context hierarchy
    五月 02, 2019 2:28:44 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [spring-aop-aspectj.xml]
    五月 02, 2019 2:28:45 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
    信息: Overriding bean definition for bean 'moocBiz' with a different definition: replacing [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [F:xiangmu3XinFuQiangSpringddwei-dao	argetclassescomimoocaopaspectjizMoocBiz.class]] with [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring-aop-aspectj.xml]]
    五月 02, 2019 2:28:45 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
    信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    around 1
    before1
    beforeWithParam:This is Test!
    MoocBiz save This is Test!
    around 2
    around :Save Success!
    after:
    AfterReturning:   Save Success!
    五月 02, 2019 2:28:45 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
    信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@7fe219e7: startup date [Thu May 02 14:28:44 CST 2019]; root of context hierarchy

    2.2  前置通知@before传递类参数

    注解类:

    package com.imooc.aop.aspectj;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    
    /**
     * 1    关于RetentionPolicy
     * 1.1 RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
     * 1.2 RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
     * 1.3 RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
     * SOURCE < CLASS < RUNTIME 
     * 
     * 
     * 2    关于ElementType.METHOD
     * 2.1    
     * 表示注解MoocMethod能用来修饰类中的Method
     * 
     * @author weijingli
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MoocMethod {
        
        String value();
    }

    切面类:

    package com.imooc.aop.aspectj;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    /**
     * 注解切面类
     * 注:本页面主要功能是:整理各种通知的注解
     * @author weijingli
     *
     */
    
    @Component
    @Aspect
    public class MoocAspect {
        
        /**
         * 该处设置切入点,主要是用来匹配目标对象类
         * 
         * 执行com.imooc.aop.aspect.biz 包下的 以Biz结尾的类的所有方法
         */
        @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")
        public void pointcut(){}
        
        
        /**
         * 执行com.imooc.aop.aspect.biz 包下的所有类的  所有方法
         */
        @Pointcut("within(com.imooc.aop.aspectj.biz.*)")
        public void bizPointcut(){}
        
        
        /**
         *     前置通知   样例1
         */
        @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")
        public void before(){
            System.out.println("before1");
        }
        
        /**
         * AfterReturning 执行后通知,接收  目标对象返回的值
         * @param reValue
         */
        @AfterReturning(pointcut="pointcut()",returning="reValue")
        public void afterReturning(Object reValue){
            System.out.println("AfterReturning:   "+reValue);
        }
        
        /**
         * 后置通知  相当于java语法中的finally
         */
        @After("pointcut()")
        public void after(){
            System.out.println("after:");
        }
        
        /**
         * 异常通知:
         * 
         * 接收异常返回的信息
         */
        @AfterThrowing(pointcut="pointcut()",throwing="e")
        public void afterThrowing(RuntimeException e){
            System.out.println("AfterThrowing: "+e.getMessage());
        }
        
        /**
         * 环绕通知:
         * @param pjp
         * @return
         * @throws Throwable
         */
        @Around("pointcut()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable{
            System.out.println("around 1");
            Object obj = pjp.proceed();
            System.out.println("around 2");
            System.out.println("around :"+obj);
            return obj;
        }
        
        
        /**
         *     前置通知   带参数
         */
        @Before("pointcut()&&args(arg)")
        public void beforeWithParam(String arg){
            System.out.println("beforeWithParam:"+arg);
        }
        
        
        /**
         *     前置通知   传入类
         */
        @Before("pointcut()&&@annotation(moocMethod)")
        public void beforeWithAnnotation(MoocMethod moocMethod){
            System.out.println("beforeWithAnnotation,"+moocMethod.value());
        }
        
        
        
        /**
         *     前置通知   样例2
         */
        /*@Before("pointcut()")
        public void before2(){
            System.out.println("before2");
        }*/
        
    
        
    
    }

    实体类:

    package com.imooc.aop.aspectj.biz;
    
    import org.springframework.stereotype.Service;
    
    import com.imooc.aop.aspectj.MoocMethod;
    
    @Service
    public class MoocBiz {
        /**
         * 1    为什么 用 save方法 返回 String 类型?
         * 
         * 答:为了方便After Or AfterReturning 通知  接收  返回值
         * 
         * 2     为什么接收String 参数?
         * 
         * 答:只是为了方便测试,没有任何实际意义。
         * @param arg
         * @return
         */
        @MoocMethod("MoocBiz save MoocMethod")
        public String save(String arg){
            System.out.println("MoocBiz save "+arg);
    //        throw new RuntimeException("Save Failed!");
            return "Save Success!";
        }
    }

    测试类:

    package com.imooc.test.aop;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.BlockJUnit4ClassRunner;
    
    import com.imooc.aop.aspectj.biz.MoocBiz;
    import com.imooc.test.base.UnitTestBase;
    
    /**    @RunWith 是一个运行器 
     *     
     * @RunWith(JUnit4.class)就是指用JUnit4来运行       
     *    
     *@RunWith(Suite.class)的话就是一套测试集合
     *
     *@RunWith(Suite.class)的话就是一套测试集合                                                 
     *                                        
     *@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件                                                  
     * 
     * @author weijingli
     */
    @RunWith(BlockJUnit4ClassRunner.class)
    public class TestAspectJ extends UnitTestBase{
    
        public TestAspectJ() {
            super("classpath:spring-aop-aspectj.xml");
        }
        
        @Test
        public void testAspectJ(){
            MoocBiz mBiz = super.getbean("moocBiz");
            mBiz.save("This is Test!");
        }
        
    
    }

    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"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
    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"
     >
    
    
    <!-- 自己添加注意:
    1    context:component-scan 扫描包,根据注解找到通知。         使用注解的时候,记得添加扫描包的功能
    2    aop:aspectj-autoproxy 通过配置织入@Aspectj切面 -->
    
    <context:component-scan base-package="com.imooc.aop.aspectj"/>
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    
     <bean id="moocBiz" class="com.imooc.aop.aspectj.biz.MoocBiz"></bean>
     
    </beans>

    打印日志:

    五月 02, 2019 3:45:28 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
    信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3f64fffc: startup date [Thu May 02 15:45:28 CST 2019]; root of context hierarchy
    五月 02, 2019 3:45:28 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    信息: Loading XML bean definitions from class path resource [spring-aop-aspectj.xml]
    五月 02, 2019 3:45:28 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory registerBeanDefinition
    信息: Overriding bean definition for bean 'moocBiz' with a different definition: replacing [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [F:xiangmu3XinFuQiangSpringddwei-dao	argetclassescomimoocaopaspectjizMoocBiz.class]] with [Generic bean: class [com.imooc.aop.aspectj.biz.MoocBiz]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [spring-aop-aspectj.xml]]
    五月 02, 2019 3:45:28 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
    信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    around 1
    before1
    beforeWithAnnotation,MoocBiz save MoocMethod
    beforeWithParam:This is Test!
    MoocBiz save This is Test!
    around 2
    around :Save Success!
    after:
    AfterReturning:   Save Success!
    五月 02, 2019 3:45:29 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
    信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@3f64fffc: startup date [Thu May 02 15:45:28 CST 2019]; root of context hierarchy
  • 相关阅读:
    ________________”一切都变了”被遗忘的 label
    ________________java常用快捷键
    Java核心技术 卷1 多线程----执行器(5)
    Java核心技术 卷1 多线程----线程安全的集合(4)
    Java核心技术 卷1 多线程----阻塞队列在线程中的使用(3)
    数据结构与算法之算法的度量方法(1)
    数据结构与算法之算法初体验(1)
    Java核心技术 卷1 多线程----线程的相关用法(2)
    Java核心技术 卷1 多线程----线程的相关概念(1)
    heap&stack 区别
  • 原文地址:https://www.cnblogs.com/1446358788-qq/p/10802252.html
Copyright © 2011-2022 走看看