Spring AOP 原理

静态代理

public class ProxyDemo {
    public static void main(String[] args) {
        RealImage realImage = new RealImage();
        ProxyImage proxyImage = new ProxyImage(realImage);
        proxyImage.doSomething();
    }
}

interface Image {
    void doSomething();
}

class RealImage implements Image {

    @Override
    public void doSomething() {
        System.out.println("Real image");
    }
}

class ProxyImage implements Image {
    private RealImage realImage;

    public ProxyImage(RealImage realImage) {
        this.realImage = realImage;
    }

    @Override
    public void doSomething() {
        System.out.println("proxy start");
        realImage.doSomething();
        System.out.println("proxy end");
    }
}

打印结果:

proxy start
Real image
proxy end

JDK 动态代理(基于接口)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyDemo {
    public static void main(String[] args) {
        Target target = new TargetImpl();
        TargetIH targetIH = new TargetIH(target);
        Class<?> clazz = target.getClass();
        Target proxyInstance = (Target) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), targetIH);
        proxyInstance.doSomething();
        proxyInstance.doSomethingElse();
    }
}

interface Target {
    void doSomething();
    void doSomethingElse();
}

class TargetImpl implements Target {

    @Override
    public void doSomething() {
        System.out.println("TargetImpl doSomething");
    }
    
    @Override
    public void doSomethingElse() {
        System.out.println("TargetImpl doSomethingElse");
    }
}

class TargetIH implements InvocationHandler {
    private Object target;

    public TargetIH(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        System.out.println("proxy start");
        Object result = null;
        try {
            result = method.invoke(target, args);
        } catch (Exception e) {
            // do something
        }
        System.out.println("proxy end");
        return result;
    }
}

打印:

proxy start
TargetImpl doSomething
proxy end
proxy start
TargetImpl doSomethingElse
proxy end

CGLIB

CGLIB (Byte Code Generation Library is high level API to generate and transform Java byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access)动态代理,不需要有接口

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.5</version>
</dependency>
import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ProxyDemo {
    public static void main(String[] args) {
        
        TargetMI interceptor = new TargetMI();
        Enhancer e = new Enhancer();
        e.setSuperclass(Target.class);
        e.setCallback(interceptor);
        Target proxyInstance = (Target) e.create();
        proxyInstance.doSomething();
    }
}

class Target {
    public void doSomething() {
        System.out.println("doSomething");
    }
}

class TargetMI implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("proxy start");
        Object retValFromSuper = proxy.invokeSuper(obj, args);
        System.out.println("proxy end");
        return retValFromSuper;
    }
}

打印:

proxy start
doSomething
proxy end

Spring AOP

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.10</version>
    </dependency>
</dependencies>
<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    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-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
<context:annotation-config />
<context:component-scan base-package="cn.zno.*" />

</beans>
package cn.zno.foo;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

public class ProxyDemo {

    public static void main(String[] args) {
        @SuppressWarnings("resource")
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        Target target = (Target) ctx.getBean(Target.class);
        target.doSomething();
        target.doSomethingElse();
    }
}

interface Target {
    public void doSomething();
    public void doSomethingElse();
}

@Component
class TargetImpl implements Target {

    @Override
    public void doSomething() {
        System.out.println("doSomething");
    }

    @Override
    public void doSomethingElse() {
        System.out.println("doSomethingElse");
    }
}

@Component // 需要注册到bean工厂,否则不会生效
@Aspect // 需要配置Spring AOP
class TargetInterceptor {
    
    @Pointcut("execution(* doSomething(..)) || execution(* doSomethingElse(..))") // the pointcut(target method) signature
    private void anysdf() {
        System.out.println("pointcut signature");
    }

    @Before(value = "anysdf()")
    public void before(JoinPoint joinPoint) {
        System.out.println("Before");
    }

    @After("anysdf()")
    public void after() {
        System.out.println("After");
    }
}

打印:

Before
doSomething
After
Before
doSomethingElse
After

原文地址:https://www.cnblogs.com/zno2/p/7522134.html