自定义注解的方式使用AOP写日志

这里用比较原生的方式实现比较利于学习和理解AOP。
1、环境准备
创建一个maven工程并导入以下依赖

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- Spring AOP + AspectJ by yinxin -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>3.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>3.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.1_3</version>
        </dependency>
        <!-- end -->
    </dependencies>

2、spring的xml配置文件将aop的代理对象和被代理对象注入ioc容器。
如图:
项目结构如图name:applicationContext-aop.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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- 使 AspectJ 的注解起作用 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <bean id="personServiceBean" class="com.yinxin.aop.AopTest.impl.personServerImpl"/>
    <bean id="myInterceptor" class="com.yinxin.aop.AopTest.AspectIntercepter"/>

</beans>

2、代码实现
自定义注解

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)
public @interface Log {
    String value() default "";
}

被代理类

//接口(按规范来)
public interface personServer {
    void save(String name,int age);
}

//实现接口的类
import com.yinxin.aop.AopTest.annotation.Log;
import com.yinxin.aop.AopTest.personServer;


public class personServerImpl implements personServer {

    @Log
    @Override
    public void save(String name, int age) {
        int a=0;
//        age = age/a;//打开上面两行报错可触发异常通知
        System.err.println("come in personServerImpl save method...");
    }
}

代理类

package com.yinxin.aop.AopTest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;


@Aspect//声明这是一个切面
@Component//声明这是一个组件,泛指...可以去掉
public class AspectIntercepter {

//    @Pointcut(value="execution(* com.yinxin.aop.AopTest.impl.personServerImpl.*(..))")//exec表达式方式
    @Pointcut(value="@annotation(com.yinxin.aop.AopTest.annotation.Log)")//注解方式
    private void pointCut(){//定义一个切入点 后面的通知直接引入切入点方法pointCut即可personServerImpl下面的所有方法

    }

    //环绕通知(连接到切入点开始执行,下一步进入前置通知,在下一步才是执行操作方法)
    @Around(value="pointCut()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("@Around进入环绕通知...");
        Object object = pjp.proceed();//执行该方法
        System.out.println(pjp.getThis()+"方法操作结束,退出方法;环绕[@Around]结束!...");
        return object;
    }

    //前置通知(进入环绕后执行,下一步执行方法)
    @Before(value="pointCut()")
    public void doAccessCheck(JoinPoint joinPoint){
        System.out.println("@Before前置通知:"+ Arrays.toString(joinPoint.getArgs()));
        /*System.out.println(joinPoint);
        System.out.println(joinPoint.getKind());
        System.out.println(joinPoint.getThis());
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//获取signature 该注解作用在方法上,强转为 MethodSignature
        System.out.println("signature.getMethod() = " + signature.getMethod());
        System.out.println("signature.getName() = " + signature.getName());
        System.out.println("signature.getParameterNames() = " + signature.getParameterNames());
        System.out.println("signature.getReturnType() = " + signature.getReturnType());
        System.out.println(joinPoint.getSourceLocation());
        System.out.println(joinPoint.getClass());
        System.out.println(joinPoint.getStaticPart());
        System.out.println(joinPoint.getTarget());*/
    }

    //异常通知(出错时执行)
//    @AfterThrowing(value="pointCut()",throwing="ex")
    public void doAfterThrow(JoinPoint joinPoint,Throwable ex){
        System.out.println("@AfterThrowing例外通知(异常通知)"+Arrays.toString(joinPoint.getArgs()));
        System.out.println("@AfterThrowing异常信息:"+ex);
    }

    //后置通知(返回之前执行)
    @After(value="pointCut()")
    public void after(){
        System.out.println("@After后置通知...");
    }

    //最终通知(正常返回通知,最后执行)
//    @AfterReturning(value="pointCut()")
    public void doAfter(){
        System.out.println("@AfterReturning最终通知...End!");
    }
}

注解(加这个注解的方法都会被aop实现方法增强)


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)
public @interface Log {
    String value() default "";
}

测试类(注意这里用了两种方式实现了方法增强,修改获取切点的表达式方法完成两种方式的切换)

import com.yinxin.aop.AopTest.personServer;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author yinxin
 * @version 1.0
 * @Description:
 * @date 2022/3/1016:34
 */
public class test {
    @Test
    public void inteceptorTest(){
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext-aop.xml");
        personServer bean = (personServer)ctx.getBean("personServiceBean");
        bean.save("badMonkey",23);

//	    	personServer p = new personServerImpl();//通过new对象是不会触发aop的
//	    	p.save("11", "22");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值