Spring之AOP剖析
一、Aop是何方神圣
AOP:Aspect Oriented Programming,即”面向切面编程“。面向切面编程是一种编程范式,是OOP面向对象编程的一种补充,用于处理系统中分布于各个模块的横切关注点,如事务管理、缓存控制、日志打印等。AOP采取横向抽取机制,取代了传统纵向继承体系的重复性代码
二、必备知识库
1、AOP专有名词讲解
(1)通知(增强)Advice
拦截到Joinpoint之后所要做的事情就是通知,通知分为前置通知、后置通知、异常通知、最终通知和环绕通知
(2)连接点 Join point
类里面可以被增强的方法
(3)切入点 Pointcut
切入点是与连接点匹配的表达式,用于确定是否需要执行通知
(4)切面 Aspect
Pointcut(切入点)和Advice(增强/通知)的结合
(5)引入 Introduction
引入允许我们向现有的类添加新方法或属性,从而无需修改这些现有类的情况下,让他们具有新的行为和状态。
(6)织入 Weaving
即把目标对象在指定的连接点织入到切面中
2、代理讲解
先创建Aspect类
@Aspect
public class MyAspect {
@Before("execution(* com.kang.*.*(..))")
public void fun1(){
System.out.println("前置增强");
}
@After("execution(* com.kang.*.*(..))")
public void fun2(){
System.out.println("后置增强");
}
}
(1)JDK动态代理 – java.lang.reflect.InvocationHandler
实现方法:
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
注: 该动态代理是基于接口的动态代理,所以使用时必须有接口被定义
(2)CGLIB代理实现 – org.springframework.cglib.proxy.Callback、 org.springframework.cglib.proxy.MethodInterceptor
3、实现方法:
public interface MethodInterceptor extends Callback {
Object intercept(Object obj, Method m, Object[] args, MethodProxy mp) throws Throwable
}
注:实现后可用mp.invoke(Object obj, Object[] args)调用同类对象的方法或用mp.invokeSuper(Object obj, Object[] args)调用父类方法。
三、具体实现
1、JDK动态代理实现
创建接口
public interface MyText {
public void myFun();
}
实现类
public class MyTextImpl implements MyText {
public void myFun(){
System.out.println("my proxy test");
}
}
public class MyProxy implements InvocationHandler{
private Object delegate;
private final Logger logger = LoggerFactory.getLogger(this.getClass();
public Object bind(Object delegate) {
this.delegate = delegate;
return Proxy.newProxyInstance(delegate.getClass().getClassLoader().delegate.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
logger.info("MyFirst Proxy");
result = method.invoke(delegate, args);
logger.info("MySecond Proxy");
} catch (Exception e) {
throw e;
}
return result;
}
public static void main(String[] args) {
MyProxy myProxy = new MyProxy();
MyText text = (MyProxy) myProxy.bind(new Fun());
text.myFun();
}
}
2、CGLIB代理实现
public class MyProxy implements MethodInterceptor {
private Object delegate;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy mp) throws Throwable {
logger.info("MyFirst Proxy");
Object result = mp.invokeSuper(method, args);
logger.info("MySecond Proxy");
return result;
}
public static MyText getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyText.class);
enhancer.setCallback(new MyProxy());
return (MyText) enhancer.create();
}
}
配置文件
<!-- 通知 -->
<bean id="advices" class="com.kang.dao"></bean>
<!-- aop配置 -->
<aop:config>
<!--切面 -->
<aop:aspect ref="advices">
<!-- 切点 -->
<aop:pointcut expression="execution(* com.kang.dao.*(..))" id="pointcut1"/>
<!--连接通知方法与切点 -->
<aop:before method="before" pointcut-ref="pointcut1"/>
<aop:after method="after" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
看了辣么多是不是很累呐,到此就随大脑去吧,放轻松不脱发。