首页 体育 教育 财经 社会 娱乐 军事 国内 科技 互联网 房产 国际 女人 汽车 游戏

深入了解Spring中的AOP

2020-05-20

谈起AOP,咱们都知道是面向切面编程,但你真的了解Spring中的AOP吗?Spring AOP、JDK动态署理、CGLIB、AspectJ之间又有什么相关和差异?

在Spring中AOP包括两个概念,一是Spring官方根据JDK动态署理和CGLIB完结的Spring AOP;二是集成面向切面编程神器AspectJ。Spring AOP和AspectJ不是竞赛联系,根据署理的结构的Spring AOP和成熟结构AspectJ都是有价值的,它们是互补的。

AOP中的术语

告诉

Spring切面能够使用5种类型的告诉:

前置告诉:在方针办法被调用之前调用告诉功用;

后置告诉:在方针办法完结之后调用告诉,此刻不会关怀办法的输出是什么;

回来告诉:在方针办法成功履行之后调用告诉;

反常告诉:在方针办法抛出反常后调用告诉;

盘绕告诉:告诉包裹了被告诉的办法,在被告诉的办法调用之前和调用之后履行自界说的行为。

连接点

切点

切面

引进

织入

这些术语的解说,其他博文中许多,这儿就不再赘述。

用2个比如来阐明Spring AOP和AspectJ的用法

现在有这样一个场景,页面传入参数当前页page和每页展现多少条数据rows,咱们需求写个阻拦器将page、limit参数转换成MySQL的分页句子offset、rows。

先看Spring AOP完结

1、完结MethodInterceptor,阻拦办法

public class MethodParamInterceptor implements MethodInterceptor { @Override @SuppressWarnings public Object invoke throws Throwable { Object[] params = invocation.getArguments; if ) { return invocation.proceed; } for  { //假如参数类型是Map if  { Map paramMap =  param; processPage; break; } } return invocation.proceed; } /** * * @param paramMap */ private void processPage { if    !paramMap.containsKey) { return; } int page = 1; int rows = 10; for ) { String key = entry.getKey; String value = entry.getValue.toString; if ) { page = NumberUtils.toInt; } else if ) { rows = NumberUtils.toInt; }else { //TODO } } int offset =  * rows; paramMap.put; paramMap.put; } } 

2、界说后置处理器,将办法阻拦件加入到advisor中。咱们经过注解@Controller阻拦一切的Controller,@RestController承继于Controller,所以一致阻拦了。

public class RequestParamPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor implements InitializingBean { private Class validatedAnnotationType = Controller.class; @Override public void afterPropertiesSet throws Exception { Pointcut pointcut = new AnnotationMatchingPointcut; this.advisor = new DefaultPointcutAdvisor); } } 

3、万事俱备只欠东风,Processor也写好了,只需求让Processor收效。

@Configuration public class MethodInterceptorConfig { @Bean public RequestParamPostProcessor converter { return new RequestParamPostProcessor; } }` 

这儿有个坑需求留意一下,假如在装备类中注入业务Bean。

@Configuration public class MethodInterceptorConfig { @Autowired private UserService userService; @Bean public RequestParamPostProcessor converter { return new RequestParamPostProcessor; } } 

启动时,会呈现:

2019-11-08 14:55:50.954 INFO 51396 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionFactory' of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory] is not eligible for getting processed by all BeanPostProcessors  2019-11-08 14:55:50.960 INFO 51396 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'sqlSessionTemplate' of type [org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors  2019-11-08 14:55:51.109 INFO 51396 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'rememberMapper' of type [com.sun.proxy.$Proxy84] is not eligible for getting processed by all BeanPostProcessors  2019-11-08 14:55:53.406 INFO 51396 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors  

许多切面失效,如业务切面。这是由于注入了自界说的Bean,自界说的Bean优先级最低,由最低优先级的BeanPostProcessor来加载并完结初始化的。但为了加载其间的RequestParamPostProcessor,导致不得不优先装载低优先级Bean,此刻业务处理器的AOP等都还没完结加载,注解业务初始化都失利了。但Spring就提示了一个INFO等级的提示,然后剩余的Bean由最低优先级的BeanPostProcessor正常处理。

AspectJ方法完结切面

@Component@Aspect@Slf4jpublic class MethodParamInterceptor { @Pointcut ) public void paramAspect { } @Before ) public void beforeDataSource { Arrays.stream).forEach { Map parameter =  paramObject; processPage; } }); } private void processPage { if  { return; } if    !paramMap.containsKey) { return; } int page = 1; int rows = 10; for ) { String key = entry.getKey; String value = entry.getValue.toString; if ) { page = NumberUtils.toInt; } else if ) { rows = NumberUtils.toInt; } } int offset =  * rows; paramMap.put; paramMap.put; } @After ) public void afterDataSource { } } 

从上面两个比如能够对比出SpringAOP和AspectJ的两种不同用法,但到达的才能是相同的。

Sping AOP在安排、笼统代码场景中愈加合适,AspectJ用于单纯的切面来完结某项功用愈加简练。

戳这儿,看该作者更多好文

热门文章

随机推荐

推荐文章