AOP概念
AOP是Aspect Oriented Programming的缩写,即『面向切面编程』。它和我们平时接触到的OOP都是编程的不同思想,OOP,即『面向对象编程』,它提倡的是将功能模块化,对象化,而AOP的思想,则不太一样,它提倡的是针对同一类问题的统一处理,当然,我们在实际编程过程中,不可能单纯的安装AOP或者OOP的思想来编程,很多时候,可能会混合多种编程思想,大家也不必要纠结该使用哪种思想,取百家之长,才是正道

AspectJ
AspectJ实际上是对AOP编程思想的一个实践,当然,除了AspectJ以外,还有很多其它的AOP实现,例如ASMDex,但目前最好、最方便的,依然是AspectJ。

Advice(通知)
注入到class文件中的代码。典型的 Advice 类型有 before、after 和 around,分别表示在目标方法执行之前、执行后和完全替代目标方法执行的代码。 除了在方法中注入代码,也可能会对代码做其他修改,比如在一个class中增加字段或者接口。

Joint point(连接点)
程序中可能作为代码注入目标的特定的点,例如一个方法调用或者方法入口。

Pointcut(切入点)
告诉代码注入工具,在何处注入一段特定代码的表达式。例如,在哪些 joint points 应用一个特定的 Advice。切入点可以选择唯一一个,比如执行某一个方法,也可以有多个选择,比如,标记了一个定义成@DebguTrace 的自定义注解的所有方法。

AspectJ提供不同类型的通知,分别为:
@Before 前置通知,相当于BeforeAdvice
@AfterReturning 后置通知,相当于AfterReturningAdvice
@Around 环绕通知,相当于MethodInterceptor
@AfterThrowing异常抛出通知,相当于ThrowAdvice
@After 最终final通知,不管是否异常,该通知都会执行

1:引入aspectj依赖

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>

 

2:新建一个User类

 

public class User {
public void add(){
System.out.println("add方法");
}
}

 

3:新建一个UserProxy类,被增强的一个类,

Before方法上加上@Before注解,配置切入点表达式,
*表示所有修饰符类型,后面加一个空格

接着后面上全路径和方法名,最后..表示参数

@Component
@Aspect //表示生成一个代理对象
public class UserProxy {

//前置通知
//@Before注解表示作为前置通知
@Before("execution(* com.example.wzy.demo.aop.User.add(..))")
public void before(){
System.out.println("before方法");
}
}

 

 

4:新建一个bean9.xml

首先加上context和aop的名称空间

接着配置开启组件扫描

<context:component-scan base-package="com.example.wzy.demo.aop"></context:component-scan>

com.example.wzy.demo.aop是全路径,表示扫描这个包

 

还有添加

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

表示开启Aspect生成代理对象,就是去类上找有没有@Aspect注解,有的话就把这个对象生成一个代理对象

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_02

 

5:最后添加一个测试类

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_03

 

6:输出结果,这就是前置通知,在方法执行之前执行

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_spring_04

 

 

 

 

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_05

@Component
@Aspect //表示生成一个代理对象
public class UserProxy {

//前置通知
//@Before注解表示作为前置通知
@Before("execution(* com.example.wzy.demo.aop.User.add(..))")
public void before() {
System.out.println("before方法");
}

//后置通知,最终通知,方法执行之后执行,有异常也会执行
@After("execution(* com.example.wzy.demo.aop.User.add(..))")
public void after() {
System.out.println("after方法");
}

//后置通知(返回通知)方法返回结果之后执行,有异常不执行
@AfterReturning("execution(* com.example.wzy.demo.aop.User.add(..))")
public void afterReturning() {
System.out.println("AfterReturning");
}

//异常通知
@AfterThrowing("execution(* com.example.wzy.demo.aop.User.add(..))")
public void afterThrowing() {
System.out.println("AfterThrowing");
}

//环绕通知
@Around("execution(* com.example.wzy.demo.aop.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕通知之前");
proceedingJoinPoint.proceed();
//被增强的方法执行
System.out.println("环绕通知之后");
}
}

 

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_xml_06

 

 

 

优化:

相同的切入点抽取,下面的都是重复的,可以提取出来,如下图

execution(* com.example.wzy.demo.aop.User.add(..))

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_07

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_08

 

 

比如对User的add方法需要两个增强类,那么使用

@Order()注解可以,里面的数字越小表示先执行

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_09

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_10

 

看下执行结果

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_xml_11

 

 

 

 

 

使用下xml配置文件配置

新建Book类和BookProxy类

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_12

public class Book {
public void buy(){
System.out.println("buy*********");
}
}

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_spring_13

public class BookProxy {
public void before(){
System.out.println("before**********");
}
}

 

2:新建bean.xml

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_System_14

<?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">
<!--名称空间-->

<!--创建对象-->
<bean id="book" class="com.example.wzy.demo.aopxml.Book"></bean>

<bean id="bookProxy" class="com.example.wzy.demo.aopxml.BookProxy"></bean>

<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* com.example.wzy.demo.aopxml.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
</beans>

 

新建测试类

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_spring_15

 

@Test
public void test2(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean10.xml");
Book book = ac.getBean("book", Book.class);
book.buy();
}

执行结果

配置的是前置通知,所以先输出before再输出buy

基于使用AspectJ实现AOP,注解AOP开发(基于xml文件、基于注解)_spring_16