Spring AOP学习:
AOP用于在模块化方面的关注点,简单来说,就是一个拦截器来拦截一些过程。
例如:当一个方法执行时,Spring AOP可以劫持一个正在执行的方法,在方法前或方法后添加一些功能。
在Spring AOP中有四种类型通知(advice)的支持:
1.该方法执行前运行
2.运行后,该方法返回一个结果
3.运行方法抛出异常后
4.环绕方法执行运行
1.在该方法执行前运行
步骤如下:
-
首先创建一个实现MethodBeforeAdvice的类,like below:
package com.ray.aop;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @author raytseng
* @create 2018/12/18-上午10:05
* @detail:
**/
public class outBeforeMethod implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("outBeforeMethod : Before method output!!");
}
}
-
接下来在applicationContext.xml文件中,创造该类的bean,like this:
<bean id="outBeforeMethodBean" class="com.ray.aop.outBeforeMethod"/>
-
然后,我们需要创建一个代理对象
bean id="customServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="customService"/>
<property name="interceptorNames">
<list>
<value>outBeforeMethodBean</value>
</list>
</property>
</bean>
-
里面‘target’定义了你想拦截的对象customService(用在谁身上)
customService代码如下:
public class CustomService {
private String name;
private String url;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public void printName(){
System.out.println("Custom Name : " + this.name);
}
public void printUrl(){
System.out.println("Custom Website : " + this.url);
}
public void printThrowException(){
throw new IllegalArgumentException();
}
}
-
interceptorNames定义了要应用这个代理对象的类(谁来用)
主函数如下:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
CustomService cust = (CustomService) context.getBean("customServiceProxy”); //换成了代理对象的id
System.out.println("***************");
cust.printName();
System.out.println("***************");
cust.printUrl();
try {
cust.printThrowException();
}catch (Exception e)
{
}
}
}
输出如下:
***************
outBeforeMethod : Before method output!!
Custom Name : RayTseng
***************
outBeforeMethod : Before method output!!
Custom Website : https://raytseng.com
outBeforeMethod : Before method output!!
2.运行后,该方法返回一个结果
与第一个方法的不同点在于,在创建继承的类时,不太相同,代码如下:
package com.ray.aop;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
* @author raytseng
* @create 2018/12/18-上午10:05
* @detail:
**/
public class outAfterMethod implements AfterReturningAdvice {
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("outAfterMethod : After method output!!!");
}
}
其他与第一种方法类似,配置文件如下:
<bean id="customService" class="com.ray.services.CustomService">
<property name="name" value="RayTseng" />
<property name="url" value="https://raytseng.com"/>
</bean>
<bean id="outAfterMethodBean" class="com.ray.aop.outAfterMethod"/>
<bean id="customServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="customService"/>
<property name="interceptorNames">
<list>
<value>outAfterMethodBean</value>
</list>
</property>
</bean>
输出如下:
***************
Custom Name : RayTseng
outAfterMethod : After method output!!!
***************
Custom Website : https://raytseng.com
outAfterMethod : After method output!!!
3.运行方法抛出异常后
它将在执行方法抛出一个异常后。创建一个实现ThrowsAdvice接口的类,并创建一个afterThrowing方法拦截抛出:IllegalArgumentException异常(我们在customService中创建的)。
新建outThrowException类
ackage com.ray.aop;
import org.springframework.aop.ThrowsAdvice;
/**
* @author raytseng
* @create 2018/12/18-上午10:05
* @detail:
**/
public class outThrowException implements ThrowsAdvice {
public void afterThrowing(IllegalArgumentException e) throws Throwable {
System.out.println("outThrowException : Throw exception output!!");
}
}
//其他文件同上述方法类似,不多讲
输出:
***************
Custom Name : RayTseng
***************
Custom Website : https://raytseng.com
outThrowException : Throw exception output!!
4.环绕方法执行运行
创建一个实现了MethodInterceptor接口的类。必须调用“methodInvocation.proceed();” 继续在原来的方法执行,否则原来的方法将不会执行。
public class OutAroundMethod 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 outBeforeMethod
System.out.println("outBeforeMethod : Before method output!");
try {
// proceed to original method call
Object result = methodInvocation.proceed();
// same with outAfterMethod
System.out.println("outAfterMethod : Before after output!");
return result;
} catch (IllegalArgumentException e) {
// same with ThrowsAdvice
System.out.println(“OutAroundMethod : Throw exception output!");
throw e;
}
}
}