概念:

切面(aspect):用来切插业务方法的类。

连接点(joinpoint):是切面类和业务类的连接点,其实就是封装了业务方法的一些基本属性,作为通知的参数来解析。

通知(advice):在切面类中,声明对业务方法做额外处理的方法。

切入点(pointcut):业务类中指定的方法,作为切面切入的点。其实就是指定某个方法作为切面切的地方。

目标对象(target object):被代理对象。

AOP代理(aop proxy):代理对象。

AOP通知类型:

前置通知(before advice):在切入点之前执行。

后置通知(after returning advice):在切入点执行完成后,执行通知。

环绕通知(around advice):包围切入点,调用方法前后完成自定义行为。

异常通知(after throwing advice):在切入点抛出异常后,执行通知

 

依赖包:


AOP AspectJ注解_xmlAOP AspectJ注解_spring_02


<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

View Code

Code:



package com.qhong;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person person=(Person)context.getBean("babyPerson");
person.eatBreakfast();
System.out.println("===================================================");
person.eatLunch();
System.out.println("===================================================");
person.eatSupper();
System.out.println("===================================================");
person.drink("可乐");
System.out.println("===================================================");
}
}

interface Person {
public void eatBreakfast();
public void eatLunch();
public void eatSupper();
public String drink(String name);
}

@Component
class BabyPerson implements Person{

@Override
public void eatBreakfast() {
System.out.println("小Baby正在吃早餐");
}

@Override
public void eatLunch() {
System.out.println("小Baby正在吃午餐");
}

@Override
public void eatSupper() {
System.out.println("小Baby正在吃晚餐");
}

@Override
public String drink(String name) {
return "小Baby在喝:"+name;
}
}

@Component
@Aspect
class AdivceMethod {

@Before("execution(* com.qhong.BabyPerson.*(..))")
// 匹配BabyPerson类所有的方法,注意*和com之间有个空格
public void beforeEat() {
System.out
.println("-------------------这里是前置增强,吃饭之前先洗小手!--------------------");
}

@After("execution(* eatLunch(..))")
// 匹配该工程下所有的eatLunch方法
public void afterEat() {
System.out
.println("-------------------这里是后置增强,午饭吃完要睡午觉!--------------------");
}

@Around("execution(* com.qhong.BabyPerson.eatSupper())")
// 匹配该工程下BabyPerson的eatLunch方法
public Object aroundEat(ProceedingJoinPoint pjp) throws Throwable {
System.out
.println("-------------------这里是环绕增强,吃晚饭前先玩一玩!-------------------");
Object retVal = pjp.proceed();
System.out
.println("-------------------这里是环绕增强,晚饭吃完后要得睡觉了!-------------------");
return retVal;
}
@AfterReturning(returning="rvt",pointcut="execution(* com.qhong.BabyPerson.drink(..))")
public void log(Object rvt) {
System.out
.println("-------------------这里是AfterReturning增强-------------------");
System.out.println("获取小Baby正在喝的饮料"+rvt);
System.out.println("记录每天喝的饮料容量");

}
}


beans.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<!-- 指定自动搜索bean组件、自动搜索切面类 -->
<context:component-scan base-package="com.qhong"/>
<!-- 启动@AspectJ支持 -->
<!-- proxy-target-class默认"false",更改为"ture"使用CGLib动态代理 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
Result:



-------------------这里是前置增强,吃饭之前先洗小手!--------------------
小Baby正在吃早餐
===================================================
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
小Baby正在吃午餐
-------------------这里是后置增强,午饭吃完要睡午觉!--------------------
===================================================
-------------------这里是环绕增强,吃晚饭前先玩一玩!-------------------
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
小Baby正在吃晚餐
-------------------这里是环绕增强,晚饭吃完后要得睡觉了!-------------------
===================================================
-------------------这里是前置增强,吃饭之前先洗小手!--------------------
-------------------这里是AfterReturning增强-------------------
获取小Baby正在喝的饮料小Baby在喝:可乐
记录每天喝的饮料容量
===================================================
Spring + AspectJ(基于注解:通过 AspectJ execution 表达式拦截方法)



package com.qhong;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
com.qhong.Greeting greeting = (com.qhong.Greeting) context.getBean("greetingImpl");
greeting.sayHello("Jack");
}
}

interface Greeting {
void sayHello(String name);
}

@Component
class GreetingImpl implements Greeting {
@Override
public void sayHello(String name) {
System.out.println("Hello! " + name);
}
}

@Aspect
@Component
class GreetingAspect {
@Around("execution(* com.qhong.GreetingImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
before();
Object result = pjp.proceed();
after();
return result;
}

private void before() {
System.out.println("Before");
}

private void after() {
System.out.println("After");
}
}


spring.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<context:component-scan base-package="com.qhong"/>

<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>


Result:



Before
Hello! Jack
After