课程链接:

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:\xiangmu3\Xin\FuQiang\Spring\ddwei-dao\target\classes\com\imooc\aop\aspectj\biz\MoocBiz.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:\xiangmu3\Xin\FuQiang\Spring\ddwei-dao\target\classes\com\imooc\aop\aspectj\biz\MoocBiz.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

 

posted on 2019-05-02 14:18  菜鸟乙  阅读(188)  评论(0编辑  收藏  举报