莫大人

AOP 实现自定义注解

1.自定义注解
2.编写 AOP
3.测试

 

 

1.自定义注解

package com.base.yun.spring.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/** 
* 说明: 
* 定义日志注解 
*/  
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface FileLog {  
    
  String value() default "记录日志";  
    
}  

 


2.编写 AOP

package com.base.yun.spring.aop;

import org.aspectj.lang.JoinPoint;
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.springframework.stereotype.Component;

/**
 * 说明: 日志的切面处理程序
 */
@Aspect
@Component
public class LogAspect {

    @Before("within(com.base.yun.spring.service.*) && @annotation(fileLog)")
    public void doAccessCheck(JoinPoint jp, FileLog fileLog) {
        System.out.println("前置通知-->>");
    }

    @After("within(com.base.yun.spring.service.*) && @annotation(fileLog)")
    public void doAfterReturning(JoinPoint jp, FileLog fileLog) {
        System.out.println("后置通知-->>");
    }

    @Around("within(com.base.yun.spring.service.*) && @annotation(fileLog)")
    public Object doAround(ProceedingJoinPoint pJoinPoint, FileLog fileLog) throws Throwable {
        System.out.println("环绕通知开始");
        // 这里如果pJoinPoint.proceed()不执行,后面拦截到的方法都不会执行,非常适用于权限管理
        Object result = pJoinPoint.proceed();
        System.out.println("环绕通知结束");
        return result;
    }

    @AfterReturning("within(com.base.yun.spring.service.*) && @annotation(fileLog)")
    public void addSuccessLog(JoinPoint jp, FileLog fileLog) {
        Object[] parames = jp.getArgs();
        // 获取目标方法体参数
        String className = jp.getTarget().getClass().toString();
        // 获取目标类名
        String signature = jp.getSignature().toString();
        // 获取目标方法签名
        String methodName = signature.substring(signature.lastIndexOf(".") + 1,
                signature.indexOf("("));
        // 获取注解值
        String desc = fileLog.value();
        // 把调用的信息写到日常记录信息里面去...
        System.out.println("最终通知注解值:"+desc);
    }

    // 标注该方法体为异常通知,当目标方法出现异常时,执行该方法体
    @AfterThrowing(pointcut = "within(com.base.yun.spring.service.*) && @annotation(fileLog)", throwing = "e")
    public void addExceptionLog(JoinPoint jp, FileLog fileLog, Exception e) {
        System.out.println("异常通知-->");
        // 把错误信息写到错误日志文件里面去...
    }
}

 


3.测试

<aop:aspectj-autoproxy/>  
     <bean class="com.base.yun.spring.aop.LogAspect"/> 
     <bean id="purchaseService" class="com.base.yun.spring.service.PurchaseService" />
package spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.base.yun.spring.service.PurchaseService;

public class AopTest {

    @Test
    public void testAop() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("user.xml");
        PurchaseService service = ctx.getBean("purchaseService",PurchaseService.class);
        service.purchaseProduct("电风扇", 98, "日用品"); 
    }
    
}

测试结果:

环绕通知开始
前置通知-->>
购买商品。。。
环绕通知结束
后置通知-->>
最终通知注解值:记录日志

 

posted on 2017-10-11 14:23  莫大人  阅读(216)  评论(0编辑  收藏  举报

导航