Spring入门四(基于注解的AOP编程、切面、切点、execution用法、五种Advice)

AOP的基本概念:面向切面编程,作用类似于反射代理。在目标方法执行前后可自动的执行其他代码(称为增强)。其他代码又被称为切面。我们要关注的是如何写其他代码而不是如何调用其他代码。因此称之为面向切面编程。

AOP编程的主要步骤

  1. 编写切面类,由多个额外的方法组成
  2. 声明pointcut,定义要增强的点,即目标方法
  3. 声明advice,指明在被代理对象的方法前、后、返回值后、抛出异常后或周围执行要执行的代码。
    1. 下面开始code...
      定义接口:接口中定义要增强的方法。早期版本只能对接口中的方法增强,后来的版本可以对普通类中的方法进行增强。
public interface EmailDao {
    public void send();
    public void receive();
}

接口的实现类:

@Component//对象的创建交给容器来管理
public class EmailDaoImpl implements EmailDao {
    @Override public void send() {
        System.out.println("发送邮件");
    }
    @Override public void receive() {
        System.out.println("收到邮件");
    }
}

定义切面:@Aspect表示这是一个切面类,切面类也是交给spring容器来管理的。用execution语句来指定增强点。可以在一个空方法上用@Pointcut来指定增强点,之后可以用方法名加扩号来取代execution语句。如下面代码中第三个方法上面。但是早期的一些版本也不支持。
execution语句解释:execution(* com.AOP.EmailDao.se*(…)),第一个*表示访问权限为任意;后面的路径表示该路径下的以se开头的方法,不写se表示任意方法,参数任意。

@Aspect
@Component
public class MyService {
    @Pointcut("execution(* com.AOP.EmailDao.re*(..))")
    public void point(){}
    @Before("execution(* com.AOP.EmailDao.se*(..))")//目标方法执行之前执行下面的代码
    public void send()
    {
        System.out.println("发送邮件之前");
    }
    @After("point()")//也可以写成@After("execution(* com.AOP.EmailDao.re*(..))"),表示该结构下的以re开头的方法执行完后都会执行以下方法。
    public void receive()
    {
        System.out.println("接受邮件之后");
    }
}

因为是基于注解,所有没有ApplicatioonContext.xml文件,要通过java类来配置:

@Configurable
@EnableAspectJAutoProxy//开启代理,一定要加
public class MyConfig {
    @Bean("email")
    public EmailDao getEmailDao()
    {
        return new EmailDaoImpl();
    }
    @Bean
    public AllService getAllService()
    {
        return new AllService();
    }
}

main方法:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        EmailDao email=(EmailDao)context.getBean("email");
        email.send();
        email.receive();
    }
}

运行结果:

发送邮件之前
发送邮件
收到邮件
接受邮件之后

验证能否对普通类中的方法进行增强,将切点的位置移动到一个普通类的一个普通方法(不是继承来的)。对该方法进行增强。

@Component
public class test {
    public void show()//要增强的方法
    {
        System.out.println("Hello world");
    }
}

切面类中:

@Before("execution(* com.AOP.test.*(..))")
 public void beforeNormalMethod()
 {
     System.out.println("hi............");
 }

配置类中:

 @Bean
 public test getTest()
 {
     return new test();
 }

main方法中:

test t=context.getBean(test.class);
t.show();

运行结果:

hi............
Hello world


返回值后进行增强:
切面类:

 @AfterReturning(value = "execution(* com.AOP.test.*(..))",returning = "retVal")
    public void afterReturnMethod(Object retVal)
    {
        System.out.println("有返回值"+((Integer)retVal+666));//对返回值加666后进行输出
    }

被切点命中的方法:

public int show()
{
    return 0;
}

运行结果:

有返回值666


方法抛出异常时进行增强:

@AfterThrowing(value = "execution(* com.AOP.test.*(..))",throwing = "exc")
    public void afterThrowingMethod(Exception exc)
    {
        System.out.println("有异常了-----"+exc);
    }

被命中的方法:

public int show()
    {
        return 10/0;//会抛出异常
    }

运行结果:

有异常了-----java.lang.ArithmeticException: / by zero


方法周围执行增强方法,相当于反射代理:

 @Around("execution(* com.AOP.test.*(..))")
    public void aroundMethod(ProceedingJoinPoint proceedingJoinPoint)throws Throwable
    {
        System.out.println("执行目标方法之前");
        proceedingJoinPoint.proceed();//执行目标方法
        System.out.println("执行目标方法之后");
    }
    public void show()
    {
        System.out.println("this is show method");
    }

运行结果:

执行目标方法之前
this is show method
执行目标方法之后

上一篇
---The End---
下一篇

你可能感兴趣的:(框架入门)