Spring AOP用法(待完善)

Cglib实现AOP

    // 切所有方法
    @Test
    public void cglib1() {
        UserService target = new UserService();
        // 通过cglib实现AOP
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);
        // 定义额外逻辑,也就是代理逻辑
        // o:代理对象;     method:被代理类方法;  objects:方法参数;   methodProxy:代理类方法
        enhancer.setCallbacks(new Callback[]{(MethodInterceptor) (o, method, objects, methodProxy) -> {
            System.out.println("before...");
            Object result = methodProxy.invoke(target, objects);
            System.out.println("after...");
            return result;
        }});
        // 动态代理所创建出来的UserService代理对象
        UserService userService = (UserService) enhancer.create();
        // 执行这个userService的test方法时,就会额外会执行一些其他逻辑
        userService.test();
    }

    // 切指定方法
    @Test
    public void cglib2() {
        UserService target = new UserService();
        // 通过cglib实现AOP
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);
        // 定义多个代理逻辑, 数组类型
        enhancer.setCallbacks(new Callback[]{(MethodInterceptor) (o, method, objects, methodProxy) -> {
            System.out.println("before...");
            Object result = methodProxy.invoke(target, objects);
            System.out.println("after...");
            return result;
        }, NoOp.INSTANCE});
        // 设置切面匹配逻辑, return对应执行的callback数组
        enhancer.setCallbackFilter(method -> {
            if("test".equals(method.getName())) {
                return 0;
            }
            return 1;
        });
        // 动态代理所创建出来的UserService代理对象
        UserService userService = (UserService) enhancer.create();
        // 执行这个userService的test方法时,就会额外会执行一些其他逻辑
        userService.test();
        userService.print();
    }

下面执行结果, 可看出, 只有test执行了额外逻辑, print执行了空代理逻辑

before...
test---------
after...
print---------

JDK动态代理实现AOP

    @Test
    public void jdkProxy1() {
        UserService target = new UserService();
        Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{UserInterface.class}, (proxy1, method, args) -> {
            System.out.println("before...");
            Object result = method.invoke(target, args);
            System.out.println("after...");
            return result;
        });
        UserInterface userInterface = (UserInterface) proxy;
        userInterface.test();
    }

ProxyFactory实现AOP

spring对cglib和jdk动态代理进行了封装, 叫做ProxyFactory代理工厂, 会自动根据是否是接口, 去切换.如果实现了接口, 用jdk动态代理, 否则用cglib动态代理.

Advice实现AOP


    // 代理类 - cglib动态代理
    @Test
    public void proxyFactory1() {
        UserService target = new UserService();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("before...");
                Object proceed = invocation.proceed();
                System.out.println("after...");
                return proceed;
            }
        });
        UserService userService = (UserService) proxyFactory.getProxy();
        userService.test();
    }

    // 代理接口 - jdk动态代理
    @Test
    public void proxyFactory2() {
        UserService target = new UserService();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAdvice(new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("before...");
                Object proceed = invocation.proceed();
                System.out.println("after...");
                return proceed;
            }
        });
        UserInterface userService = (UserInterface) proxyFactory.getProxy();
        userService.test();
    }

Advisor实现AOP

@Test
    public void proxyFactory3() {
        UserService target = new UserService();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAdvisor(new PointcutAdvisor() {
            @Override
            public Pointcut getPointcut() {
                return new StaticMethodMatcherPointcut() {
                    @Override
                    public boolean matches(Method method, Class targetClass) {
                        return "test".equals(method.getName());
                    }
                };
            }

            @Override
            public Advice getAdvice() {
                return new MethodInterceptor() {
                    @Override
                    public Object invoke(MethodInvocation invocation) throws Throwable {
                        System.out.println("before...");
                        Object proceed = invocation.proceed();
                        System.out.println("after...");
                        return proceed;
                    }
                };
            }

            @Override
            public boolean isPerInstance() {
                return false;
            }
        });
        UserService userService = (UserService) proxyFactory.getProxy();
        userService.test();
        userService.print();
    }

Spring实现AOP

@Component
@Aspect
public class KhAspect {

    @Before("execution(public void org.example.spring.service.UserService.test())")
    public void khBefore(JoinPoint joinPoint) {
        System.out.println("KhAspect Before");
    }
}

@EnableAspectJAutoProxy
@ComponentScan("org.example.spring.service")
public class AppConfig {
}

@Component
public class UserService implements UserInterface {

    public void test() {
        System.out.println("test---------");
    }

    public void print() {
        System.out.println("print---------");
    }
}

public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 如果实现了接口, 默认用jdk代理
        UserInterface userService = (UserInterface) context.getBean("userService");
        System.out.println(userService);
        userService.test();
    }
}

AOP概念

  • Aspect: 表示切面,@Aspect注解定义的类就是切面, 切面可以定义PointCut和Advice
  • Join point:表示连接点, 一个连接点表示一个方法的执行
  • Adivce: 表示通知, 有前置通知, 后置通知,环绕通知等, 来实现增强逻辑,
  • PointCut:表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上
  • Introduction:可以使用@DeclareParents来给所匹配的类添加一个接口,并指定一个默认实现
  • Weaving:表示织入,表示创建代理对象的动作,这个动作可以发生在编译时期(比如Aspejctj),或者运行时,比如Spring AOP

你可能感兴趣的:(spring,java,后端)