'Java'에 해당되는 글 102건

  1. 2014.08.14 Spring AOP 예제
  2. 2014.08.13 Spring+MyBatis 의 DataSource Routing (1)
  3. 2014.07.16 Tomcat Https 적용
  4. 2014.07.07 [Spring] 다중 DB 트랜잭션 처리
  5. 2014.07.07 Google Protocol Buffer proto 파일로 C# class Generate 하기
  6. 2013.09.23 Nexus Repository Manager 구축하기 ( for maven )
  7. 2011.04.12 Reflection 호출의 성능 저하 테스트
  8. 2011.03.30 2011 게임테크의 현장 세부 내용
  9. 2011.02.16 Apache Derby 많이 좋아졌네요.
  10. 2010.10.04 Java FX 속도 괄목 상대 할정도로 속도가 상승했군요. :)
  11. 2010.10.04 Mina Network new update
  12. 2010.08.26 [BPM] BPM 이란 무엇인가 ( UEngine)
  13. 2010.08.09 DVCS Mercurial 설치/활용
  14. 2010.08.05 Svn Apply Patch 수행시에 인코딩이 깨져 merge가 안되는 현상 (1)
  15. 2010.07.23 새로운 Version Control Git & Mercurial
  16. 2009.11.05 11월 5일 JDK6 Updat17 릴리즈
  17. 2009.10.27 저만 생각하는게 아니었군요. AbstractEnum
  18. 2009.10.12 SingleTon 패턴을 우회해 인스턴스를 생성하는 방법.
  19. 2009.09.16 이런~ ORACLE의 SUN 합병 그후
  20. 2009.09.09 Java 직렬화(Serialization)의 원리를 파헤쳐 보자 (1)
  21. 2009.08.25 JDK7 - 새로운 기능들
  22. 2009.08.18 JDK6 update16 업데이트
  23. 2009.07.14 Apache DB 드디어 메모리 DB 지원
  24. 2009.06.30 그래픽 카드 메모리 정보 가져오기
  25. 2009.06.05 Too Many Open Files Exception
  26. 2009.06.04 JDK7 에 NUMA 시스템에 대한 성능 변화가?
  27. 2009.05.20 새로운 JVM 기반 언어 Clojure ( 클로져 ) (1)
  28. 2009.04.13 속도 빠른 ! 이클립스를 위한 DB Viewer Plug-in ( No default DB )
  29. 2009.04.08 속도가 중요할까 잘짜여진 프레임웍이 중요할까. (1)
  30. 2009.04.01 DB 아이템 테이블 구조

Spring AOP 예제

Java 2014.08.14 10:30

http://www.journaldev.com/2583/spring-aop-example-tutorial-aspect-advice-pointcut-joinpoint-annotations-xml-configuration

Spring AOP Example Tutorial – Aspect, Advice, Pointcut, JoinPoint, Annotations, XML Configuration

Spring Framework is developed on two core concepts – Dependency Injection and Aspect Oriented Programming (AOP). We have already see how Spring Dependency Injection works, today we will look into the core concepts of Aspect Oriented Programming and how we can implement it using Spring Framework.

Aspect Oriented Programming Overview

Most of the enterprise applications have some common crosscutting concerns that is applicable for different types of Objects and modules. Some of the common crosscutting concerns are logging, transaction management, data validation etc. In Object Oriented Programming, modularity of application is achieved by Classes whereas in Aspect Oriented Programming application modularity is achieved by Aspects and they are configured to cut across different classes.

AOP takes out the direct dependency of crosscutting tasks from classes that we can’t achieve through normal object oriented programming model. For example, we can have a separate class for logging but again the functional classes will have to call these methods to achieve logging across the application.

Aspect Oriented Programming Core Concepts

Before we dive into implementation of AOP in Spring Framework, we should understand the core concepts of AOP.

  1. Aspect: An aspect is a class that implements enterprise application concerns that cut across multiple classes, such as transaction management. Aspects can be a normal class configured through Spring XML configuration or we can use Spring AspectJ integration to define a class as Aspect using @Aspectannotation.
  2. Join Point: A join point is the specific point in the application such as method execution, exception handling, changing object variable values etc. In Spring AOP a join points is always the execution of a method.
  3. Advice: Advices are actions taken for a particular join point. In terms of programming, they are methods that gets executed when a certain join point with matching pointcut is reached in the application. You can think of Advices as Struts2 interceptors or Servlet Filters.
  4. Pointcut: Pointcut are expressions that is matched with join points to determine whether advice needs to be executed or not. Pointcut uses different kinds of expressions that are matched with the join points and Spring framework uses the AspectJ pointcut expression language.
  5. Target Object: They are the object on which advices are applied. Spring AOP is implemented using runtime proxies so this object is always a proxied object. What is means is that a subclass is created at runtime where the target method is overridden and advices are included based on their configuration.
  6. AOP proxy: Spring AOP implementation uses JDK dynamic proxy to create the Proxy classes with target classes and advice invocations, these are called AOP proxy classes. We can also use CGLIB proxy by adding it as the dependency in the Spring AOP project.
  7. Weaving: It is the process of linking aspects with other objects to create the advised proxy objects. This can be done at compile time, load time or at runtime. Spring AOP performs weaving at the runtime.

AOP Advice Types

Based on the execution strategy of advices, they are of following types.

  1. Before Advice: These advices runs before the execution of join point methods. We can use @Beforeannotation to mark an advice type as Before advice.
  2. After (finally) Advice: An advice that gets executed after the join point method finishes executing, whether normally or by throwing an exception. We can create after advice using @After annotation.
  3. After Returning Advice: Sometimes we want advice methods to execute only if the join point method executes normally. We can use @AfterReturning annotation to mark a method as after returning advice.
  4. After Throwing Advice: This advice gets executed only when join point method throws exception, we can use it to rollback the transaction declaratively. We use @AfterThrowing annotation for this type of advice.
  5. Around Advice: This is the most important and powerful advice. This advice surrounds the join point method and we can also choose whether to execute the join point method or not. We can write advice code that gets executed before and after the execution of the join point method. It is the responsibility of around advice to invoke the join point method and return values if the method is returning something. We use @Around annotation to create around advice methods.

The points mentioned above may sound confusing but when we will look at the implementation of Spring AOP, things will be more clear. Let’s start creating a simple Spring project with AOP implementations. Spring provides support for using AspectJ annotations to create aspects and we will be using that for simplicity. All the above AOP annotations are defined in org.aspectj.lang.annotation package.

Spring Tool Suite provides useful information about the aspects, so I would suggest you to use it. If you are not familiar with STS, I would recommend you to have a look at Spring MVC Tutorial where I have explained how to use it.

Create a new Simple Spring Maven project so that all the Spring Core libraries are included in the pom.xml files and we don’t need to include them explicitly. Our final project will look like below image, we will look into the Spring core components and Aspect implementations in detail.

Spring-AOP-Example-Project

Spring AOP AspectJ Dependencies

Spring framework provides AOP support by default but since we are using AspectJ annotations for configuring aspects and advices, we would need to include them in the pom.xml file.

pom.xml
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
64
65
66
67
68
69
70
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework.samples</groupId>
    <artifactId>SpringAOPExample</artifactId>
    <version>0.0.1-SNAPSHOT</version>
 
    <properties>
 
        <!-- Generic properties -->
        <java.version>1.6</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
        <!-- Spring -->
        <spring-framework.version>4.0.2.RELEASE</spring-framework.version>
 
        <!-- Logging -->
        <logback.version>1.0.13</logback.version>
        <slf4j.version>1.7.5</slf4j.version>
 
        <!-- Test -->
        <junit.version>4.11</junit.version>
 
        <!-- AspectJ -->
        <aspectj.version>1.7.4</aspectj.version>
 
    </properties>
 
    <dependencies>
        <!-- Spring and Transactions -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>
 
        <!-- Logging with SLF4J & LogBack -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
            <scope>runtime</scope>
        </dependency>
 
        <!-- AspectJ dependencies -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
</project>

Notice that I have added aspectjrt and aspectjtools dependencies (version 1.7.4) in the project. Also I have updated the Spring framework version to be the latest one as of date i.e 4.0.2.RELEASE.

Model Class

Let’s create a simple java bean that we will use for our example with some additional methods.

Employee.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.journaldev.spring.model;
 
import com.journaldev.spring.aspect.Loggable;
 
public class Employee {
 
    private String name;
     
    public String getName() {
        return name;
    }
 
    @Loggable
    public void setName(String nm) {
        this.name=nm;
    }
     
    public void throwException(){
        throw new RuntimeException("Dummy Exception");
    }
     
}

Did you noticed that setName() method is annotated with Loggable annotation. It is a custom java annotationdefined by us in the project. We will look into it’s usage later on.

Service Class

Let’s create a service class to work with Employee bean.

EmployeeService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.journaldev.spring.service;
 
import com.journaldev.spring.model.Employee;
 
public class EmployeeService {
 
    private Employee employee;
     
    public Employee getEmployee(){
        return this.employee;
    }
     
    public void setEmployee(Employee e){
        this.employee=e;
    }
}

I could have used Spring annotations to configure it as a Spring Component, but we will use XML based configuration in this project. EmployeeService class is very standard and just provides us an access point for Employee beans.

Spring Bean Configuration with AOP

If you are using STS, you have option to create “Spring Bean Configuration File” and chose AOP schema namespace but if you are using some other IDE, you can simply add it in the spring bean configuration file.

My project bean configuration file looks like below.

spring.xml
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
<?xml version="1.0" encoding="UTF-8"?>
 
<!-- Enable AspectJ style of Spring AOP -->
<aop:aspectj-autoproxy />
 
<!-- Configure Employee Bean and initialize it -->
<bean name="employee" class="com.journaldev.spring.model.Employee">
    <property name="name" value="Dummy Name"></property>
</bean>
 
<!-- Configure EmployeeService bean -->
<bean name="employeeService" class="com.journaldev.spring.service.EmployeeService">
    <property name="employee" ref="employee"></property>
</bean>
 
<!-- Configure Aspect Beans, without this Aspects advices wont execute -->
<bean name="employeeAspect" class="com.journaldev.spring.aspect.EmployeeAspect" />
<bean name="employeeAspectPointcut" class="com.journaldev.spring.aspect.EmployeeAspectPointcut" />
<bean name="employeeAspectJoinPoint" class="com.journaldev.spring.aspect.EmployeeAspectJoinPoint" />
<bean name="employeeAfterAspect" class="com.journaldev.spring.aspect.EmployeeAfterAspect" />
<bean name="employeeAroundAspect" class="com.journaldev.spring.aspect.EmployeeAroundAspect" />
<bean name="employeeAnnotationAspect" class="com.journaldev.spring.aspect.EmployeeAnnotationAspect" />
 
</beans>

For using AOP in Spring beans, we need to do following:

  1. Declare AOP namespace like xmlns:aop=”http://www.springframework.org/schema/aop”
  2. Add aop:aspectj-autoproxy element to enable Spring AspectJ support with auto proxy at runtime
  3. Configure Aspect classes as other Spring beans

You can see that I have a lot of aspects defined in the spring bean configuration file, it’s time to look into those one by one.

Before Aspect Example

EmployeeAspect.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.journaldev.spring.aspect;
 
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
 
@Aspect
public class EmployeeAspect {
 
    @Before("execution(public String getName())")
    public void getNameAdvice(){
        System.out.println("Executing Advice on getName()");
    }
     
    @Before("execution(* com.journaldev.spring.service.*.get*())")
    public void getAllAdvice(){
        System.out.println("Service method getter called");
    }
}

Important points in above aspect class is:

  • Aspect classes are required to have @Aspect annotation.
  • @Before annotation is used to create Before advice
  • The string parameter passed in the @Before annotation is the Pointcut expression
  • getNameAdvice() advice will execute for any Spring Bean method with signature public String getName(). This is a very important point to remember, if we will create Employee bean using new operator the advices will not be applied. Only when we will use ApplicationContext to get the bean, advices will be applied.
  • We can use asterisk (*) as wild card in Pointcut expressions, getAllAdvice() will be applied for all the classes in com.journaldev.spring.service package whose name starts with get and doesn’t take any arguments.

We will look these advices in action in a test class after we have looked into all the different types of advices.

Pointcut Methods and Reuse

Sometimes we have to use same Pointcut expression at multiple places, we can create an empty method with @Pointcut annotation and then use it as expression in advices.

EmployeeAspectPointcut.java
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