一、前言

  使用注解代替之前在spring配置文件中配置目标类、切面类和aop配置。

二、注意

  • 需要注意的是,需要在spring配置文件中引入如下,如果不添加,切面类中的@Aspect注解将不起作用
<aop:aspectj-autoproxy/>
  • 使用的时候通知单独使用

  • 导入的jar包

      

三、注解的使用

切面类:

  @Aspect  声明切面,修饰切面类,从而获得 通知。

通知:

       @Before 前置

       @AfterReturning 后置

       @Around 环绕

       @AfterThrowing 抛出异常

       @After 最终

切入点:

       @PointCut ,修饰方法 private void xxx(){}  之后通过“方法名”获得切入点引用

四、代码实现

beans.xml

    <!-- 扫描注解 -->
    <context:component-scan base-package="com.xx"/>
    <!-- aspectj自动代理 -->
    <aop:aspectj-autoproxy/>

切面类:通知单独使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.xx.myaspect;
 
import java.util.Arrays;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
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.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
 * 切面类
 * @author phoebe
 * @Component:类级注解
 * @Aspect:切面注解
 */
@Component
@Aspect
@Order(1)
public class MyAscpect {
     
    /*
     * 切点,方法名即是切点的id
     * 后面的切点直接引用方法名称即可
     * 方法体不需要再配置其他
     */
    @Pointcut(value="execution(* com.xx.dao.UserDaoImpl.*(..))")
     
     
    public void pointCut(){}
    /*
     * 前置通知
     * JoinPoint:带有方法名称
     */
    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("方法名称是:"+methodName);
    }
     
    /*
     * 环绕通知需要携带ProceedingJoinPoint类型的参数
     * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
     *  而且环绕通知必须有返回值,返回值即为目标方法的返回值
     
     */
    @Around(value="pointCut()")
    public Object arround(ProceedingJoinPoint pjp){
        Object obj = null;
        String methodName = pjp.getSignature().getName();
        try {
            //前置通知@Before
            System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjp.getArgs()));
            //执行目标方法
            obj = pjp.proceed();
            //后置通知@After
            System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjp.getArgs()));
        } catch (Throwable e) {
            //异常通知@AfterThrowing
            System.out.println("The method " + methodName + " occurs expection : " + e);
            throw new RuntimeException(e);
        }
        //返回通知@AfterReturning
        System.out.println("The method " + methodName + " ends");
        return obj;
    }
     
}

 

 dao接口类:

1
2
3
4
5
6
7
8
9
package com.xx.dao;
 
public interface UserDao {
 
    public void run1();
    public void run2();
    public void run3();
     
}

 dao实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.xx.dao;
import org.springframework.stereotype.Repository;
 
@Repository("userDaoImpl")
public class UserDaoImpl implements UserDao{
    @Override
    public void run1() {
        int x = 1/0;
        System.out.println("run1");
    }
    @Override
    public void run2() {
        System.out.println("run2");
    }
    @Override
    public void run3() {
        System.out.println("run3");
    }
}

 测试类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.xx;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xx.dao.UserDao;
 
public class Test {
    public static void main(String[] args) {
        String xmlPath = "classpath:beans.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
        UserDao userDao = (UserDao) context.getBean("userDaoImpl");
        userDao.run1();
        userDao.run2();
        userDao.run3();
    }
}