非Spring管理Bean如何添加AOP呢?

开发 前端
首先要清楚的是AOP的底层实现原理就是字节码,我们只需要从字节码层面,就一定可以解决这样的问题。因此可以利用编译期增强和运行期增强,常见的方案有两种,一种Java Agent技术,另一种 AspectJ方案。

[[357003]]

 前几天有个朋友问了一个问题,觉得可以给大家分享一下。

问题如下图

归其根本这是个历史项目,里面有很多的类并没有交给spring管理,但现在需要统一添加日志。

面对这样的问题,其实只要了解AOP的原理,就会有多种方法。AOP都是基于动态代理来实现,而动态代理常见的就是cglib和java动态代理,不了解的可以看下之前干货君写的文章

  • java动态代理为什么需要基于接口
  • cglib动态代理对类没有任何限制吗?

但此两种方法似乎在这样的场景不好实现,需要修改大量的代码,那么有没有什么好的方案呢?

答案当然是有。

首先要清楚的是AOP的底层实现原理就是字节码,我们只需要从字节码层面,就一定可以解决这样的问题。因此可以利用编译期增强和运行期增强,常见的方案有两种,一种Java Agent技术,另一种 AspectJ方案。

Java Agent

Java Agent中文名字叫做java 探针,可以在运行java时指定探针程序,对原程序无侵入,常见的一些APM工具都会这样,如skywalking,后续有机会给大家介绍下。如下图


java agent的主要原理就是利用JVMTI(JVM Tool Interface),JVM用来暴露一些供用户扩展的接口集合,因此可以在此处做一些运行期字节码增强。

Java Agent内容比较多,有很多大家熟悉的工具都是基于它去做的,例如阿里的arthas。本文就不介绍了,后期会给大家详细介绍下Java Agent。

AspectJ方案

可以利用aspectj + javac来编译织入代码,也可以利用maven插件aspectj-maven-plugin,下面利用AspectJ注解 + aspectj-maven-plugin来实战一下。

aspectj-maven-plugin官网 http://www.mojohaus.org/aspectj-maven-plugin/usage.html

引入依赖

编译增强,依赖此jar

 

import org.aspectj.lang.annotation.Aspect; 
 
import org.aspectj.lang.annotation.Before; 
 
import org.aspectj.lang.annotation.Pointcut; 
 
@Aspect 
 
public class Aop { 
 
 
 
@Pointcut("execution(* com.ganhuojun.gracefulshutdown.controller..*.*(..))"
 
public void pointcut1(){ 
 
 
 

 
 
 
@Before("pointcut1()"
 
public void before(){ 
 
System.out.println("controller before"); 
 

 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

 

定义注解

注意:该注解不要交给spring管理

<plugin> 
 
<groupId>org.codehaus.mojo</groupId> 
 
<artifactId>aspectj-maven-plugin</artifactId> 
 
<version>1.11</version> 
 
<configuration> 
 
<complianceLevel>1.8</complianceLevel> 
 
<source>1.8</source> 
 
<!--<showWeaveInfo>true</showWeaveInfo>--> 
 
<!--<Xlint>ignore</Xlint>--> 
 
<encoding>UTF-8</encoding> 
 
<sources> 
 
<source> 
 
<basedir>src/main/java</basedir> 
 
<!--此处使用include一致会导致织入失败,暂时未找到好的解决办法,不写则引用所有的Aspect--> 
 
<!--<includes>--> 
 
<!--<include>**/Aop.java</include>--> 
 
<!--<include>**/ControllerAop.aj</include>--> 
 
<!--</includes>--> 
 
<excludes> 
 
<exclude>**/ServiceAop.java</exclude> 
 
</excludes> 
 
</source> 
 
</sources> 
 
</configuration> 
 
<executions> 
 
<execution> 
 
<goals> 
 
<goal>compile</goal> 
 
</goals> 
 
</execution> 
 
</executions> 
 
</plugin> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

 

 配置maven插件

<plugin> 
 
<groupId>org.codehaus.mojo</groupId> 
 
<artifactId>aspectj-maven-plugin</artifactId> 
 
<version>1.11</version> 
 
<configuration> 
 
<complianceLevel>1.8</complianceLevel> 
 
<source>1.8</source> 
 
<!--<showWeaveInfo>true</showWeaveInfo>--> 
 
<!--<Xlint>ignore</Xlint>--> 
 
<encoding>UTF-8</encoding> 
 
<sources> 
 
<source> 
 
<basedir>src/main/java</basedir> 
 
<!--此处使用include一致会导致织入失败,暂时未找到好的解决办法,不写则引用所有的Aspect--> 
 
<!--<includes>--> 
 
<!--<include>**/Aop.java</include>--> 
 
<!--<include>**/ControllerAop.aj</include>--> 
 
<!--</includes>--> 
 
<excludes> 
 
<exclude>**/ServiceAop.java</exclude> 
 
</excludes> 
 
</source> 
 
</sources> 
 
</configuration> 
 
<executions> 
 
<execution> 
 
<goals> 
 
<goal>compile</goal> 
 
</goals> 
 
</execution> 
 
</executions> 
 
</plugin> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

 

 排除spring的aop

如果对spring aop比较熟悉的都知道,spring的aop也是基于AspectJ的,因此需要exclude的,已经配置到mavn的地方了。

编译&运行&测试

编译后class文件已经被织入了相关代码,如下图


运行相关日志输出如下

 说明功能已经实现。

 

责任编辑:姜华 来源: 今日头条
相关推荐

2024-05-28 07:55:31

SpringBean用域

2021-05-06 07:58:57

Spring BeanIOCAOP

2021-03-08 08:40:25

Spring Bean 创建单例对象

2022-06-07 07:58:45

SpringSpring AOP

2009-06-19 13:28:30

Spring AOPSpring 2.0

2023-11-03 08:19:18

SpringBean容器

2022-02-17 13:39:09

AOP接口方式

2009-06-22 10:41:34

Spring.AOP

2023-11-27 08:17:05

SpringJava

2024-05-29 08:19:03

2022-06-08 08:04:28

Springservicerepository

2009-09-29 10:00:40

Spring AOP框

2009-06-19 11:09:27

Spring AOP

2023-10-16 11:12:29

2022-05-27 08:25:55

容器Spring

2024-02-23 10:33:34

SpringBean容器

2024-11-04 16:29:19

2021-03-01 23:26:41

日志Spring BootAOP

2022-06-23 10:47:57

Spring容器工具

2023-03-29 08:24:30

点赞
收藏

51CTO技术栈公众号