AOP:面向切面编程
一个普通类 --> 有特定功能的类 之前的方法(继承类,实现接口,注解,配置)
逻辑:
将业务类,通知,纳入springIOC容器 定义切入点,定义通知类,通过pointcut-ref将两端连接起来 各种通知在XML配置文件中的操作都是一样的
前置通知实现步骤:
jar 包 aopaliance.jar aspectjweaver.jar配置 引入aop命名空间: xmlns:aop=“http://www.springframework.org/schema/aop”
applicationContext.xml
<!-- 配置前置通知
-->
<!-- addLoad()所在方法
-->
<bean id
="log" class="cust.zaw.aop.Log"></bean
>
<!-- 前置通知 类
-->
<bean id
="logBefore" class="cust.zaw.aop.LogBefore"></bean
>
<!-- 将addLoad() 和 通知 进行关联
-->
<aop
:config
>
<!-- 前置切入点 (在哪里插入
)-->
<aop
:pointcut expression
="execution(public void cust.zaw.aop.Log.addLog())" id
="poioncut"/>
<!-- advisor
: 相当于 链接切入点 和 切面的线
-->
<aop
:advisor advice
-ref
="logBefore" pointcut
-ref
="poioncut"/>
</aop
:config
>
编写测试代码 aop:每当执行addLog()之前,自动执行一个方法before(); addLog();业务方法 before();自动执行的通知,即aop的前置通知
package cust
.zaw
.aop
;
public class Log {
public void addLog() {
System
.out
.println("addLoad()方法");
}
}
package cust
.zaw
.aop
;
import java
.lang
.reflect
.Method
;
import org
.springframework
.aop
.MethodBeforeAdvice
;
public class LogBefore implements MethodBeforeAdvice{
@Override
public void before(Method arg0
, Object
[] arg1
, Object arg2
) throws Throwable
{
System
.out
.println("前置通知");
}
}
package cust
.zaw
.aop
;
import org
.springframework
.context
.ApplicationContext
;
import org
.springframework
.context
.support
.ClassPathXmlApplicationContext
;
public class AopTest {
public static void main(String
[] args
)
{
ApplicationContext context
= new ClassPathXmlApplicationContext("applicationContext.xml");
Log log
=(Log
)context
.getBean("log");
log
.addLog();
}
}
输出:
前置通知
addLoad()方法
如果是多个方法要使用同一个前置通知, 代码要作以下修改
public void deleteLog() {
System
.out
.println("deleteLogLoad()方法");
}
ApplicationContext context
= new ClassPathXmlApplicationContext("applicationContext.xml");
Log log
=(Log
)context
.getBean("log");
log
.addLog();
log
.deleteLog();
/上面的的配置语句就要写成下面这样(用or来连接)
aop
:pointcut expression
="
execution(public void cust
.zaw
.aop
.Log
.addLog())
or
execution(public void cust
.zaw
.aop
.Log
.deleteLog())" id="poioncut"
/>
输出:
前置通知
addLoad()方法
前置通知
deleteLogLoad()方法
xml方式的通知类型
通知类型需要实现的接口
前置通知org.springframework.aop.MethodBeforeAdvice后置通知org.springframework.aop.AfterReturningAdvice异常通知org.springframework.aop.ThrowsAdvice环绕通知org.aoplliance.intercept.MethodInterceptor
前置通知 在目标方法执行前实施增强,可以应用于权限管理等功能。后置通知 在目标方法执行后实施增强,可以应用于关闭流、上传 文件、删除 临时文件等功能。环绕通知 在目标方法执行前后实施增强,可以应用于日志、事务管理等功能。异常抛出通知 在方法抛出异常后实施增强,可以应用于处理异常记录日志等功能。引介通知 在目标类中添加一些新的方法和属性,可以应用于修改老版本程序。
异常通知
根据异常通知接口的定义可以发现, 异常通知的实现类 必须 编写以下方法(a 或 b)
public void afterThrowing([Method
,args
,target
],ThrowableSubclass
):
a
.public void afterThrowing(Method
,args
,target
,ThrowableSubclass
)
b
.public void afterThrowing(ThrowableSubclass
)
环绕通知
在目标方法的前后,异常发生时,最终等各个地方都可以 进行的通知,最强大的一个通知;可以或获取目标方法的全部控制权 (目标方法是否执行,执行之前,执行之后,参数,返回值等)
在使用环绕通知时,目标方法的一切信息 都可以通过 arg0 参数获取到
环绕通知底层时通过拦截器实现的
package cust
.zaw
.aop
;
import org
.aopalliance
.intercept
.MethodInterceptor
;
import org
.aopalliance
.intercept
.MethodInvocation
;
public class LogAround implements MethodInterceptor{
@Override
public Object
invoke(MethodInvocation arg0
) throws Throwable
{
Object result
=null;
try {
System
.out
.println("环绕通知实现前置通知");
result
= arg0
.proceed();
System
.out
.println("环绕通知实现后置通知");
}catch(Exception e
) {
System
.out
.println("环绕通知实现异常通知");
}
return result
;
}
}
输出:
环绕通知实现前置通知
addLoad()方法
环绕通知实现后置通知