前言
上篇文章分享了Spring的IOC,本篇文章将分享AOP
一、AOP是什么?
AOP全称(Aspect Oriented Programming)面向切片编程的简称
AOP的作用:
利用AOP对业务逻辑的各个部分进行隔离,降低业务逻辑的耦合性,提高程序的可重用型和开发效率。
常见的通知
前置通知 方法执行前调用
后置通知 方法执行后调用
返回通知 方法返回后调用
异常通知 方法出现异常调用
环绕通知 动态代理、手动推荐方法运行
连接点(Joinpoint)
程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法调用时、异常抛出时、方法返回后等等。
切入点(Pointcut)
通知定义了切面要发生的“故事”,连接点定义了“故事”发生的时机,那么切入点就定义了“故事”发生的地点
代理(proxy)
应用通知的对象,详细内容参见设计模式里面的动态代理模式。
目标(Target)
即被通知的对象
适配器(Advisor)
适配器=通知(Advice)+切入点(Pointcut)
通知(Advice)
在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)
二、常见通知
1.前置通知
MyMethodBeforeAdvice :
package com.zhw.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.MethodBeforeAdvice;
/**
* 前置通知
* 买书、评论前加系统日志。
* @author zhw
*
*/
public class MyMethodBeforeAdvice implements MethodBeforeAdvice{
@Override
public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
// 目标对象的类名
String clzName=arg2.getClass().getName();
// 当前调用的方法是
String methodName=arg0.getName();
// 当前调用方法所传递参数
String args=Arrays.toString(arg1);
System.out.println("【系统日志】:"+clzName+"."+methodName+"被调用,传递的参数为:"+args);
}
}
spring-context.xml
<!-- 目标对象 -->
<bean class="com.zhw.biz.impl.BookBizImpl"></bean>
<!-- 前置通知 -->
<bean class="com.zhw.advice.MyMethodBeforeAdvice" id="myBefore"></bean>
<!-- 代理对象=目标+通知 -->
<bean class="org.springframework.aop.framework.ProxyFactoryBean" id="bookProxy">
<!-- 目标 -->
<property name="target" ref="bookBiz"></property>
<!-- 目标所实现的接口列表 -->
<property name="proxyInterfaces">
<list>
<value>com.zhw.biz.BookBiz</value>
</list>
</property>
<!-- 通知 : 正式调用目标方法的时候,会调用下面指定的通知-->
<property name="interceptorNames">
<list>
<value>myBefore</value>
</list>
</property>
</bean>
Demo01
package com.zhw.demo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zhw.biz.BookBiz;
public class Demo01 {
@SuppressWarnings("resource")
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
// BookBiz bean =(BookBiz) context.getBean("bookBiz");
BookBiz bean =(BookBiz) context.getBean("bookProxy");
bean.buy("???", "666", 999d);
bean.comment("未知", "什么东西?");
}
}
2.后置通知
MyAfterReturningAdvice
package com.zhw.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
public class MyAfterReturningAdvice implements AfterReturningAdvice{
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
// 目标对象的类名
String clzName=arg3.getClass().getName();
// 当前调用的方法是
String methodName=arg1.getName();
// 当前调用方法所传递参数
String args=Arrays.toString(arg2);
System.out.println("【买书返利】:"+clzName+"."+methodName+"被调用,传递的参数为:"+args+";目标对象方法返回值为:"+arg0);
}
}
3.环绕通知
MyMethodInterceptor:
package com.zhw.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.cglib.proxy.MethodProxy;
/**
* 环绕通知=前置通知+后置通知
* @author zhw
*
*/
public class MyMethodInterceptor implements MethodInterceptor{
public Object invoke(MethodInvocation arg0) throws Throwable {
// 目标对象的类名
String clzName=arg0.getThis().getClass().getName();
// 当前调用的方法是
String methodName=arg0.getMethod().getName();
// 当前调用方法所传递参数
String args=Arrays.toString(arg0.getArguments());
System.out.println("【环绕通知】:"+clzName+"."+methodName+"被调用,传递的参数为:"+args);
//方法的返回值 执行目标方法 bookBiz.buy(...,...,...);
Object rs = arg0.proceed();
System.out.println("【环绕通知】:目标对象方法返回值为:"+rs);
return rs;
}
}
4.异常通知
MyThrowsAdvice
package com.zhw.advice;
import org.springframework.aop.ThrowsAdvice;
import com.zhw.exception.PriceException;
public class MyThrowsAdvice implements ThrowsAdvice{
public void afterThrowing(PriceException p) {
System.out.println("【异常通知】:当前价格发生异常,执行此代码块");
}
}
5.过滤通知
总结
以上就是今天要讲的内容,本文仅仅简单介绍了Spring——AOP