Spring AOP + AspectJ

Using AspectJ is more flexible and powerful.

Spring AOP (Aspect-oriented programming) framework is used to modularize cross-cutting concerns in aspects. Put it simple, it’s just an interceptor to intercept some processes, for example, when a method is execute, Spring AOP can hijack the executing method, and add extra functionality before or after the method execution.

In Spring AOP, 4 type of advices are supported :

  • Before advice – Run before the method execution
  • After returning advice – Run after the method returns a result
  • After throwing advice – Run after the method throws an exception
  • Around advice – Run around the method execution, combine all three advices above.

Following example show you how Spring AOP advice works.

Simple Spring example

Create a simple customer service class with few print methods for demonstration later.

package com.mkyong.customer.services;

public class CustomerService {
private String name;
private String url; public void setName(String name) {
this.name = name;
} public void setUrl(String url) {
this.url = url;
} public void printName() {
System.out.println("Customer name : " + this.name);
} public void printURL() {
System.out.println("Customer website : " + this.url);
} public void printThrowException() {
throw new IllegalArgumentException();
} }

File : Spring-Customer.xml – A bean configuration file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
<property name="name" value="Yong Mook Kim" />
<property name="url" value="http://www.mkyong.com" />
</bean> </beans>

Run it

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mkyong.customer.services.CustomerService; public class App {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "Spring-Customer.xml" }); CustomerService cust = (CustomerService) appContext.getBean("customerService"); System.out.println("*************************");
cust.printName();
System.out.println("*************************");
cust.printURL();
System.out.println("*************************");
try {
cust.printThrowException();
} catch (Exception e) { } }
}

Output

*************************
Customer name : Yong Mook Kim
*************************
Customer website : http://www.mkyong.com
*************************

A simple Spring project to DI a bean and output some Strings.

Spring AOP Advices

Now, attach Spring AOP advices to above customer service.

1. Before advice

It will execute before the method execution. Create a class which implements MethodBeforeAdvice interface.

package com.mkyong.aop;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice; public class HijackBeforeMethod implements MethodBeforeAdvice
{
@Override
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("HijackBeforeMethod : Before method hijacked!");
}
}

In bean configuration file (Spring-Customer.xml), create a bean for HijackBeforeMethod class , and a new proxy object named ‘customerServiceProxy‘.

  • ‘target’ – Define which bean you want to hijack.
  • ‘interceptorNames’ – Define which class (advice) you want to apply on this proxy /target object.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
<property name="name" value="Yong Mook Kim" />
<property name="url" value="http://www.mkyong.com" />
</bean> <bean id="hijackBeforeMethodBean" class="com.mkyong.aop.HijackBeforeMethod" /> <bean id="customerServiceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="customerService" /> <property name="interceptorNames">
<list>
<value>hijackBeforeMethodBean</value>
</list>
</property>
</bean>
</beans>

Note

To use Spring proxy, you need to add CGLIB2 library. Add below in Maven pom.xml file.

	<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>

Run it again, now you get the new customerServiceProxybean instead of the original customerService bean.

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.customer.services.CustomerService; public class App {
public static void main(String[] args) {
ApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] { "Spring-Customer.xml" }); CustomerService cust =
(CustomerService) appContext.getBean("customerServiceProxy"); System.out.println("*************************");
cust.printName();
System.out.println("*************************");
cust.printURL();
System.out.println("*************************");
try {
cust.printThrowException();
} catch (Exception e) { } }
}

Output

*************************
HijackBeforeMethod : Before method hijacked!
Customer name : Yong Mook Kim
*************************
HijackBeforeMethod : Before method hijacked!
Customer website : http://www.mkyong.com
*************************
HijackBeforeMethod : Before method hijacked!

It will run the HijackBeforeMethod’s before() method, before every customerService’s methods are execute.

2. After returning advice

It will execute after the method is returned a result. Create a class which implements AfterReturningAdvice interface.

package com.mkyong.aop;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice; public class HijackAfterMethod implements AfterReturningAdvice
{
@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
System.out.println("HijackAfterMethod : After method hijacked!");
}
}

Bean configuration file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
<property name="name" value="Yong Mook Kim" />
<property name="url" value="http://www.mkyong.com" />
</bean> <bean id="hijackAfterMethodBean" class="com.mkyong.aop.HijackAfterMethod" /> <bean id="customerServiceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="customerService" /> <property name="interceptorNames">
<list>
<value>hijackAfterMethodBean</value>
</list>
</property>
</bean>
</beans>

Run it again, Output

*************************
Customer name : Yong Mook Kim
HijackAfterMethod : After method hijacked!
*************************
Customer website : http://www.mkyong.com
HijackAfterMethod : After method hijacked!
*************************

It will run the HijackAfterMethod’s afterReturning() method, after every customerService’s methods that are returned result.

3. After throwing advice

It will execute after the method throws an exception. Create a class which implements ThrowsAdvice interface, and create a afterThrowing method to hijack the IllegalArgumentException exception.

package com.mkyong.aop;

import org.springframework.aop.ThrowsAdvice;

public class HijackThrowException implements ThrowsAdvice {
public void afterThrowing(IllegalArgumentException e) throws Throwable {
System.out.println("HijackThrowException : Throw exception hijacked!");
}
}

Bean configuration file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
<property name="name" value="Yong Mook Kim" />
<property name="url" value="http://www.mkyong.com" />
</bean> <bean id="hijackThrowExceptionBean" class="com.mkyong.aop.HijackThrowException" /> <bean id="customerServiceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="customerService" /> <property name="interceptorNames">
<list>
<value>hijackThrowExceptionBean</value>
</list>
</property>
</bean>
</beans>

Run it again, output

*************************
Customer name : Yong Mook Kim
*************************
Customer website : http://www.mkyong.com
*************************
HijackThrowException : Throw exception hijacked!

It will run the HijackThrowException’s afterThrowing() method, if customerService’s methods throw an exception.

4. Around advice

It combines all three advices above, and execute during method execution. Create a class which implements MethodInterceptor interface. You have to call the “methodInvocation.proceed();” to proceed on the original method execution, else the original method will not execute.

package com.mkyong.aop;

import java.util.Arrays;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; public class HijackAroundMethod implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable { System.out.println("Method name : "
+ methodInvocation.getMethod().getName());
System.out.println("Method arguments : "
+ Arrays.toString(methodInvocation.getArguments())); // same with MethodBeforeAdvice
System.out.println("HijackAroundMethod : Before method hijacked!"); try {
// proceed to original method call
Object result = methodInvocation.proceed(); // same with AfterReturningAdvice
System.out.println("HijackAroundMethod : Before after hijacked!"); return result; } catch (IllegalArgumentException e) {
// same with ThrowsAdvice
System.out.println("HijackAroundMethod : Throw exception hijacked!");
throw e;
}
}
}

Bean configuration file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customerService" class="com.mkyong.customer.services.CustomerService">
<property name="name" value="Yong Mook Kim" />
<property name="url" value="http://www.mkyong.com" />
</bean> <bean id="hijackAroundMethodBean" class="com.mkyong.aop.HijackAroundMethod" /> <bean id="customerServiceProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="customerService" /> <property name="interceptorNames">
<list>
<value>hijackAroundMethodBean</value>
</list>
</property>
</bean>
</beans>

Run it again, output

*************************
Method name : printName
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer name : Yong Mook Kim
HijackAroundMethod : Before after hijacked!
*************************
Method name : printURL
Method arguments : []
HijackAroundMethod : Before method hijacked!
Customer website : http://www.mkyong.com
HijackAroundMethod : Before after hijacked!
*************************
Method name : printThrowException
Method arguments : []
HijackAroundMethod : Before method hijacked!
HijackAroundMethod : Throw exception hijacked!

It will run the HijackAroundMethod’s invoke() method, after every customerService’s method execution.

Conclusion

Most of the Spring developers are just implements the ‘Around advice ‘, since it can apply all the advice type, but a better practice should choose the most suitable advice type to satisfy the requirements.

Pointcut

In this example, all the methods in a customer service class are intercepted (advice) automatically. But for most cases, you may need to use Pointcut and Advisor to intercept a method via it’s method name.

Spring AOP Example – Advice的更多相关文章

  1. Spring AOP 中 advice 的四种类型 before after throwing advice around

    spring  AOP(Aspect-oriented programming) 是用于切面编程,简单的来说:AOP相当于一个拦截器,去拦截一些处理,例如:当一个方法执行的时候,Spring 能够拦截 ...

  2. Spring AOP增强(Advice)

    Sring AOP通过PointCut来指定在那些类的那些方法上织入横切逻辑,通过Advice来指定在切点上具体做什么事情.如方法前做什么,方法后做什么,抛出异常做什么. Spring中有两种方式定义 ...

  3. Spring Aop——给Advice传递参数

    给Advice传递参数 Advice除了可以接收JoinPoint(非Around Advice)或ProceedingJoinPoint(Around Advice)参数外,还可以直接接收与切入点方 ...

  4. Spring AOP 创建Advice 定义pointcut、advisor

    前面定义的advice都是直接植入到代理接口的执行之前和之后,或者在异常发生时,事实上,还可以对植入的时机定义的更细. Pointcut定义了advice的应用时机,在Spring中pointcutA ...

  5. Spring AOP 创建Advice 基于Annotation

    public interface IHello { public void sayHello(String str); } public class Hello implements IHello { ...

  6. spring aop的五种通知类型

    昨天在腾讯课堂看springboot的视频,老师随口提问,尼玛竟然回答错了.特此记录! 问题: Spring web项目如果程序启动时出现异常,调用的是aop中哪类通知? 正确答案是: 异常返回通知. ...

  7. spring aop 的五种通知类型

    本文转自:http://blog.csdn.net/cqabl/article/details/46965197 spring aop通知(advice)分成五类: 前置通知[Before advic ...

  8. 《Spring 5官方文档》 Spring AOP的经典用法

    原文链接 在本附录中,我们会讨论一些初级的Spring AOP接口,以及在Spring 1.2应用中所使用的AOP支持. 对于新的应用,我们推荐使用 Spring AOP 2.0来支持,在AOP章节有 ...

  9. 尚硅谷spring aop详解

    spring的aop实现我们采用AspectJ的方式来实现,不采用spring框架自带的aop aspect实现有基于注解的方式,有基于xml的方式,首先我们先讲基于注解的方式,再将基于xml的方式 ...

随机推荐

  1. Html,Css,Javascript及其他的注释方法详解

    一.HTML的注释方法<!-- html注释:START -->内容<!-- html注释:END --> 包含在“<!--”与“-->”之间的内容将会被浏览器忽略 ...

  2. BZOJ 3123 森林(函数式线段树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...

  3. Android开发之消息机制

    转:http://stackvoid.com/introduction-to-Message-Handler-in-Android/ http://blog.dreamtobe.cn/2016/03/ ...

  4. Redis VS Memcached

    1. Redis & Memecached比较   内存管理 持久化 数据类型 客户端支持 并发性能 Memcached 预分配的内存池的方式 不支持持久化 支持简单的key-value存储 ...

  5. Codeforces Round #243 (Div. 2) C. Sereja and Swaps(优先队列 暴力)

    题目 题意:求任意连续序列的最大值,这个连续序列可以和其他的 值交换k次,求最大值 思路:暴力枚举所有的连续序列.没做对是因为 首先没有认真读题,没看清交换,然后,以为是dp或者贪心 用了一下贪心,各 ...

  6. UVa 12230 (期望) Crossing Rivers

    题意: 从A到B两地相距D,之间有n段河,每段河有一条小船,船的位置以及方向随机分布,速度大小不变.每段河之间是陆地,而且在陆地上行走的速度为1.求从A到B的时间期望. 分析: 我们只要分析每段河的期 ...

  7. UVALive 4043 Ants(二分图完美匹配)

    题意:每个蚁群有自己的食物源(苹果树),已知蚂蚁靠气味辨别行进方向,所以蚁群之间的行动轨迹不能重叠.现在给出坐标系中n个蚁群和n棵果树的坐标,两两配对,实现以上要求.输出的第 i 行表示第 i 个蚁群 ...

  8. 【Mac】Mac键盘实现Home, End, Page UP, Page DOWN

     * Home键=Fn+左方向    * End键=Fn+右方向    * PageUP=Fn+上方向    * PageDOWN=Fn+下方向    * 向后删除=Fn+delete  * Find ...

  9. LwIP编译方法以及选项说明

    条件编译命令 作用说明 IP_SOF_BROADCAST   LWIP_IGMP  

  10. Oracle 课程八之性能优化之Oracle SQL Trace

    一. SQL_TRACE 当SQL语句出现性能问题时,我们可以用SQL_TRACE来跟踪SQL的执行情况,通过跟踪,我们可以了解一条SQL或者PL/SQL包的运行情况,SQL_TRACE命令会将SQL ...