扩展Spring切面功能
概述
Spring的切面(Spring动态代理)在Spring中应用十分广泛,例如还有事务管理,重试等等。网上介绍SpringAop源码很多,这里假设你对SpringAop有基本的了解。如果你认为Spring代理类会创建多重代理,那说明你真的没了解。
需求背景
假设我现在想提供一个jar包,这个jar包会拦截制定注解方法,并做一些记录。这里要分析一下具体需求
拦截的注解是在方法上
如果注解是放在方法上,那么我们完全可以使用SpringAop的方式,通过自己定义一个注解,并对该注解进行拦截即可。这个不是本篇文章的重点,拦截制定注解的很简单。
拦截的注解是在类上
如果我们需要拦截的注解是类上,这里首先介绍第一个接口
Advisor
public interface Advisor {
Advice getAdvice();
boolean isPerInstance();
}
这个接口简单来说就是持有一个通知(Advice),但是一般不直接使用这个接口,因为这个对通知没有一个有效的过滤(当然如果你想对所有方法都进行拦截),所以一般是使用PointcutAdvisor,
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
这个接口就可以通过Pointcut做一些限制。为什么呢? 直接看AopUtils#findAdvisorsThatCanApply方法,这个方法就是从所有Advisor接口实现Bean选择对某个Class有效。
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//!!!有兴趣的可以重点看一下重点看这里实现,就不大段贴代码了
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
好了,我们知道了,要想让我们的自定义的切面生效,首先,
第一步,创建一个Advisor
public class MyAdvisor implements PointcutAdvisor {
//这个是Spring提供的一个简单的通过注解来获取切点类
AnnotationMatchingPointcut annotationMatchingPointcut = new AnnotationMatchingPointcut(MyAop.class);
//这个是我们自己实现的继承于Advice,
MyAdvice myAdvice =new MyAdvice();
@Override
public Pointcut getPointcut() {
return annotationMatchingPointcut;
}
@Override
public Advice getAdvice() {
return myAdvice;
}
@Override
public boolean isPerInstance() {
return false;
}
//简单起见,就直接使用MethodInterceptor
class MyAdvice implements MethodInterceptor{
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("haha");
return invocation.proceed();
}
}
第二步,定义一个开关注解,让我们的自定义切面生效
创建一个开关注解,就是一个套路,先创建一个开关注解,@import我们一个Bean注册类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(MyImporter.class)
public @interface EnableMyAop {
}
在Bean注册类中把我们的MyAdvisor注册进去吧
public class MyImporter implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
register(registry,MyAdvisor.class);
}
private void register(BeanDefinitionRegistry registry, Class<?> aopBeanFactoryPostClass) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setBeanClass(aopBeanFactoryPostClass);
registry.registerBeanDefinition(aopBeanFactoryPostClass.getSimpleName(),rootBeanDefinition);
}
}
至此,只要使用MyAop注解的类,在调用他的任何方法的时候(类内部调用不算),都会进入到我们的切面中。
小结
本篇文章是简单看了一下Spring Aop源码后,尝试自己进行扩展,因此可能不是最优的方法。不过希望能起到抛砖迎玉作用,在其基础上可以做很多有很意思的事情。如果有兴趣可以进一步研究spring自己的Advice,Pointcut的实现类。
扩展Spring切面功能的更多相关文章
- 扩展Spring切面
概述 Spring的切面(Spring动态代理)在Spring中应用十分广泛,例如还有事务管理,重试等等.网上介绍SpringAop源码很多,这里假设你对SpringAop有基本的了解.如果你认为Sp ...
- Spring Boot2.0+中,自定义配置类扩展springMVC的功能
在spring boot1.0+,我们可以使用WebMvcConfigurerAdapter来扩展springMVC的功能,其中自定义的拦截器并不会拦截静态资源(js.css等). @Configur ...
- 实现WebMvcConfigurer接口扩展Spring MVC的功能
前言: 先查看WebMvcConfigurer接口中都定义了哪些内容 public interface WebMvcConfigurer { default void configurePathMat ...
- [02] Spring主要功能模块概述
1.Spring主要功能模块 1.1 Core Container Spring的核心容器模块,其中包括: Beans Core Context SpEL Beans和Core模块,是框架的基础部 ...
- Spring 核心功能演示
Spring 核心功能演示 Spring Framework 简称 Spring,是 Java 开发中最常用的框架,地位仅次于 Java API,就连近几年比较流行的微服务框架 SpringBoot, ...
- Spring切面编程步骤
什么是面向切面编程 面向对象的编程主要注重核心业务,而面向切面编程主要关注一些不是核心的业务,但又是必须的辅助功能,比如一个完整的系统中,记录平时系统运行时抛出的异常,需要我们去记录,以便我们对系统尽 ...
- 第5章 Spring Boot 功能
Spring Boot 功能 本节将会介绍Spring Boot的一些细节. 在这里,您可以了解您将要使用和自定义的主要功能. 如果还没有准备好,您可能需要阅读第二部分“入门指南”和第三部分“使用 S ...
- 使用C++扩展Python的功能 转自:http://blog.csdn.net/magictong/article/details/8897568#comments
使用C++扩展Python的功能 环境 VS2005Python2.5.4 Windows7(32位) 简介 长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python ...
- Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试
Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试 需要FQ才能安装,使用时应该不用FQ了,除非使用postman的历史记录功能: 非常棒的C ...
随机推荐
- Apache Spark 2.2.0 中文文档 - Spark RDD(Resilient Distributed Datasets)论文 | ApacheCN
Spark RDD(Resilient Distributed Datasets)论文 概要 1: 介绍 2: Resilient Distributed Datasets(RDDs) 2.1 RDD ...
- Python之面向对象与类
本节内容 面向对象的概念 类的封装 类的继承 类的多态 静态方法.类方法 和 属性方法 类的特殊成员方法 子类属性查找顺序 一.面向对象的概念 1. "面向对象(OOP)"是什么? ...
- pygame_第一个窗口程序
####可以使用python自带的IDLE交互式开发,也可以借助其他的编辑器,我这里采用的pycharm编辑器 1.导入我们所需要的模块 import pygame,sys --导入我们需要的模块 ...
- E. Exposition
E. Exposition time limit per tes ...
- 2013 ACM/ICPC Asia Regional Chengdu Online hdu4731 Minimum palindrome
Minimum palindrome Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- 【微信小程序】调用wx.request接口需要注意的问题
写在前面 之前写了一篇<微信小程序实现各种特效实例>,上次的小程序的项目我负责大部分前端后台接口的对接,然后学长帮我改了一些问题.总的来说,收获了不少吧! 现在项目已经完成,还是要陆陆续续 ...
- webpack2使用ch10-处理图片(png jpg svg 等) 限制图片 压缩图片
1 目录展示 安装依赖 "file-loader": "^0.11.1", "image-webpack-loader": "^3 ...
- python中html解析-Beautiful Soup
1. Beautiful Soup的简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.pyt ...
- zoj3432 Find the Lost Sock 亦或的运用
只有一个出现奇数次,答案就是它了: #include<cstdio> #include<cstdlib> #include<iostre ...
- DataGrid 得到DataGridRow 和DataGridColumn
/* ---------------------------------------------------------- 文件名称:DataGridPlus.cs 作者:秦建辉 MSN:splash ...