Spring左膀之AOP

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>

看了辣么多是不是很累呐,到此就随大脑去吧,放轻松不脱发。


   转载规则


《Spring左膀之AOP》 kang 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录