一、 AOP(Aspect Oriented Programming),即面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的补充和完善。
AOP中的机制:横向切面机制:将核心功能与非核心功能隔离,在不修改源码的情况下,只在需要用到非核心功能时动态添加非核心功能。
AOP中几个重要的概念:
1、连接点:类中能够(需要)被增强的方法称为连接点
2、切点 : 类中实际被增强的方法称为切入点。
3、通知/增强(advice):在切入点实现增强的功能(方法)。分前置、后置、环绕、异常、最终(后置通知之后)通知五类。
4、切面(Aspect):切面可以是切点+增强。或者
举例说明:
方法addEmp()、deleteEmp()、insertEmp()都可以称为连接点,addEmpp()是需要增强功能的方法,称为切点。
切点与连接点的关系:连接点可能是切点,切点一定是连接点。
:
Logger类即是切面,切面里的方法before()、after()、finals()即为通知/增强。
AOP实现:
一、配置实现
1、导入约束文件、配置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">
<!-- 配置bean-->
<bean id="empService" class="org.lanqiao.aop.EmpService"/>
<bean id="logger" class="org.lanqiao.aop.Logger"/>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面(切点+增强) -->
<aop:aspect ref="logger">
<!-- 配制切入点:id为切点的别名-->
<aop:pointcut expression="execution(* org.lanqiao.aop.EmpService.addEmp())" id="qdbm"/>
<!--前置增强 -->
<aop:before method="before" pointcut-ref="qdbm"/>
<!--后置增强 -->
<aop:after-returning method="after" pointcut-ref="qdbm"/>
<!--最终增强 -->
<aop:after method="finals" pointcut-ref="qdbm"/>
<!--环绕增强 -->
<aop:around method="around" pointcut-ref="qdbm"/>
</aop:aspect>
</aop:config>
</beans>
2、Bean对象
package org.lanqiao.aop;
public class EmpService {
public void addEmp(){
System.out.println("核心业务");
}
}
3、AOP-切面
package org.lanqiao.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
//增强的业务
public class Logger {
//前置增强
public void before(){
System.out.println("before");
}
//后置增强
public void after(){
System.out.println("after-returning");
}
//环绕增强(必须带参数)
public void around(ProceedingJoinPoint joinPort){
System.out.println("around-1");
try {
joinPort.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("around-2");
}
//最终增强
public void finals(){
System.out.println("after");
}
}
4、测试
package org.lanqiao.test;
import org.junit.Test;
import org.lanqiao.aop.EmpService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
@Test
public void testAop(){
ApplicationContext context=new ClassPathXmlApplicationContext("配置文件名(如:spring-aop.xml");
EmpService emp=context.getBean("empService",EmpService.class);
((ClassPathXmlApplicationContext)context).close();//context对象没有提供clase()方法
emp.addEmp();
}
}
5、测试结果
1、在切点加入前置、后置、最终增强
结果:
before
核心业务
after-returning
after
2、在切点加入前置、后置、环绕增强
结果:
before
around-1
核心业务
around-2
after-returning
补充:*通配符
配置切点execution(* org.lanqiao.aop.EmpService.addEmp())" ----其中全路径+方法名()为指定方法名()(addEmp())为切点。 execution(* org.lanqiao.aop.EmpService.*(..))"------*(..)表示EmpService中连接点都可以作为切点 execution(* org.lanqiao.aop.*.*(..))"----表示org.lanqiao.aop包下所以连节点都可以作为切点
二、注解实现
<?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="org.lanqiao.aops"/> <!-- 初始化 aop--> <aop:aspectj-autoproxy/> </beans>
然后在类中加注解
@Component //bean 共4个注解功能一样只是名字不一样
@Aspect //定义切面
@Pointcut//定义切点
@增强的标签名(切点)