面向切面编程(Aspect Oriented Programming,AOP)
作用:不惊动原始设计的基础上为其进行增强功能
AOP术语:Aspect、Joinpoint、Pointcut、Advice、TargetObject、Proxy、AOP proxy和Weaving
(1)Joinpoint(连接点):在Spring AOP中,连接点就是指方法的调用。(我们制造出来的全部方法都是连接点),它实际上是对象的一个操作,如方法的调用或异常的抛出。
(2)Pointcut(切入点):对你要追加功能的方法或类就是切入点。在程序中,切入点指的是类或者方法名,如某个通知要应用到所有以add开头的方法中,那么所有满足这个规则的方法都是切入点。
(3)Advice(通知/增强处理):把相同的功能方法(共性功能)抽取出来的那些方法。指AOP框架在特定切入点执行的增强处理,即在定义好的切入点处所要执行的程序代码,可以将其理解为切面类中的方法。它是切面的具体实现。(我们要把通知封装成通知类)
(4)Aspect(切面):有很多很多通知,怎么知道加在哪个方法上?这就需要切面把通知和切入点绑定在一块,切面描述的是通知里的共性功能与切入点之间的关系,需要在配置文件中通过<bean>元素指定。
(5)Target Object(目标对象):指所有被通知的对象,也称为被增强对象。如果AOP框架采用的是动态的AOP实现,那么该对象就是一个被代理对象。
(6)Proxy(代理):指将通知应用到目标对象之后,被态创建的对象。
(7)AOP proxy(AOP代理):指由AOP框架所创建的对象,实现执行增强处理方法等功能。
(8)Weaving(织入):将切面代码插入到目标对象上,从而生成代理对象的过程。
在原始设计的程序中找到共性功能,并把它们抽取出来写一个通知类,在通知类中定义一个方法叫通知。然而不是所有方法都需要执行通知的,这就要把要执行的方法抽取出来定义成切入点。
AOP入门程序(基于注解方法):
1.导包:
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency>
2. dao包中创建接口和接口实现类:
package org.exampletest.annotation.dao;public interface TestDao {public void save();
}
接口实现类:
package org.exampletest.annotation.dao;import org.exampletest.annotation.dao.TestDao;
import org.springframework.stereotype.Repository;@Repository("testDao")
public class TestDaoImpl implements TestDao {@Overridepublic void save(){System.out.println("TestDao save");}
}
3.为共性功能单独创建一个通知类:
package org.exampletest.aop;public class MyAdvice {public void method(){System.out.println("共性功能");}
}
4. 在通知类里定义切入点
先定义一个空方法 private void pt(){},然后在上面写上
@Pointcut("execution(void org.exampletest.annotation.dao.TestDaoImpl.save())")
意思是:当执行到这个org.exampletest.annotation.dao.TestDaoImpl.save()方法的时候执行某些通知,这个方法就是切入点
package org.exampletest.aop;public class MyAdvice {@Pointcut("execution(void org.exampletest.annotation.dao.TestDao.save())")private void pt(){}public void method(){System.out.println("共性功能");}
}
5.绑定共性功能与切入点之间的关系
在method()方法上绑定,想在什么时候执行:比如在切入点的之前执行
package org.exampletest.aop;public class MyAdvice {@Pointcut("execution(void org.exampletest.annotation.dao.TestDao.save())")private void pt(){}@Before("pt()")public void method(){System.out.println("共性功能");}
}
6.添加注解
package org.exampletest.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component//告诉Spring这是一个bean
@Aspect//告诉Spring下面这是一个切面,是用来做AOP的,(但还需要在配置类中启动这个切面,添加@EnableAspectJAutoProxy)
public class MyAdvice {@Pointcut("execution(void org.exampletest.annotation.dao.TestDao.save())")private void pt(){}@Before("pt()")public void method(){System.out.println("共性功能");}
}
7.创建SpringConfig配置类:扫描org.exampletest包下的所有的Bean,并启动切面
package org.exampletest;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan(basePackages = "org.exampletest")
@EnableAspectJAutoProxy
public class SpringConfig {
}
8.创建测试类:
import org.exampletest.SpringConfig;
import org.exampletest.annotation.dao.TestDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class TestAop {public static void main(String[] args){ApplicationContext appCon = new AnnotationConfigApplicationContext(SpringConfig.class);TestDao td = appCon.getBean(TestDao.class);td.save();}
}
目前流行的AOP框架有两个,分别为Spring AOP和AspectJ。Spring AOP使用纯Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类织入增强的代码。AspectJ是一个基于Java语言的AOP框架,从Spring2.0版开始,Spring AOP引入了对AspectJ的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横 向代码的织入。
如图:

