Spring AOP + AspectJ

Chiwa Kantawong (Pea)
2 min readMar 15, 2017

AOP หรือ aspect-oriented programming เป็น paradigm สำหรับแก้ปัญหาความซ้ำซ้อนของ code
เอาไว้แก้ปัญหาเรื่อง Cross cutting concern ครับ
ยกตัวอย่างง่าย ๆ เช่นเรามีระบบ โอนเงินจากบัญชีหนึ่งไปยังอีกบัญชีหนึ่ง
งานหลัก ๆ ก็คือ ลดเงินของบัญชีนึงเพิ่มใส่อีกบัญชีนึง
แต่เราจะมี cross cutting concern เช่น security authentication,
transection management, logging message เป็นต้น
เราก็จะใช้ AOP เข้ามาช่วยลดความซ้ำซ้อนของ Code ส่วนต่า่งๆ เหล่านี้ที่ซ้ำๆ กัน
เข้ามาช่วย พอละ ๆ ทฤษฎียิ่งพูดยิ่งงง 555 เรามาดูตัวอย่างกันดีกว่าครับ
เข้าใจได้ดีกว่าเยอะ

ในบทความนี้เราจะใช้ AspectJ กันนะครับ อธิบายง่าย ๆ
AspectJ ก็เป็นภาษาส่วนขยายที่ทำให้ Java สามารถทำ AOP ได้นั่นเอง

Source code : https://bitbucket.org/zengcode/spring-aop-aspectj

เช่นเคยครับ ตัวอย่างจะเป็น maven project โดยใช้ spring boot นะครับ เริ่มต้นด้วย pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>4.0.0</modelVersion>

<groupId>org.springframework</groupId>
<artifactId>spring-aop-aspectj</artifactId>
<version>0.1.0</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>

</dependencies>


<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

สร้าง MyService ขึ้นมา จะมี method hello

package zengcode.medium.com.service;

import org.springframework.stereotype.Service;

@Service
public class MyService {

public void hello() {
System.out.println("Say Hello!!!!!!");
}
}

ต่อไปสร้าง LoggingAspectJ เพื่อทดสอบการทำ aop ของเรา โดยจะมี 2 method คือ logBefore() และ logAfter ซึ่งจะทำการพิมพ์ข้อความ ก่อนและหลังการทำงานของ Service และ Method ที่เราต้องการ ในที่นี้ผม กำหนดเป็น
“execution(* zengcode.medium.com.service.*.*(..))”
มซึ่งก็หมายถึงทุก Service ใน zengcode.medium.com.service และทุกๆ method

package zengcode.medium.com.aspectj;

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.springframework.stereotype.Service;

@Aspect
@Service
public class LoggingAspectJ {

@Before("execution(* zengcode.medium.com.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {

System.out.println("logBefore() is running!");
System.out.println("Package : " + joinPoint.getSignature().getDeclaringTypeName());
System.out.println("Method : " + joinPoint.getSignature().getName());
System.out.println("******");
System.out.println();
}

@After("execution(* zengcode.medium.com.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {

System.out.println();
System.out.println("******");
System.out.println("logAfter() is running!");
}

}

ต่อไปเรามาสร้าง main application

package zengcode.medium.com;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import zengcode.medium.com.service.MyService;

@SpringBootApplication
@EnableAutoConfiguration
public class Application {

private final static Logger log = LoggerFactory.getLogger(Application.class);


public static void main(String[] args) throws Exception {

ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
Application application = ctx.getBean(Application.class);

MyService myService = ctx.getBean(MyService.class);
myService.hello();
}

}

เมื่อเราลองรันดู ก็จะได้ Output ดังข้างล่างนะครับ

logBefore() is running!
Package : zengcode.medium.com.service.MyService
Method : hello
******

Say Hello!!!!!!

*****
logAfter() is running!

ลองทำความเข้าใจและนำไปใช้ดูนะครับ

--

--