我们知道Spring有两个重要的特性:IOC和AOP ,大学期间只是对Spring有一个粗浅的认识,认为spring就是配置类,建立bean,然后就可以调用类的方法。直到慢慢了解才知道Spring还有很深的东西,Spring的强大。
这篇博文主要讲述Spring AOP 的 hijack(拦截) 功能,主要描述为当我们在执行一个类的方法的时候我们可以在方法执行前和执行后增加额外的方法
原文就是 Spring AOP can hijack the executing method,and add extra functionality before or after the method execution
我们先声明一个实体类,CustomerService
- package com.kwe.bean; /**
- * bean
- * @author rey.yang
- *
- */
- 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();
- }
- }
配置文件spring-customer.xml 放在src的根目录下:
- <?xml version="1.0" encoding="UTF-8"?>
- <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.kwe.bean.CustomerService">
- <property name="name" value="yang yang"></property>
- <property name="url" value="http://www.youkuaiyun.com"></property>
- </bean>
- </beans>
测试配置是否OK?
- 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) {
- }
- }
- }
输出如下:
- *************************
- Customer name : yang yang
- *************************
- Customer website : http://www.youkuaiyun.com
- *************************
我们建立一个拦截类HijackBeforeMethod继承MethodBeforeAdvice
- public class HijackBeforeMethod implements MethodBeforeAdvice{
- @Override
- public void before(Method method, Object[] args, Object target)
- throws Throwable {
- System.out.println("HijackBeforeMethod:Before method hijack");
- }
- }
然后在spring-customer2.xml下配置:
- <bean id="customerService" class="com.kwe.bean.CustomerService">
- <property name="name" value="yang yang"></property>
- <property name="url" value="http://www.youkuaiyun.com"></property>
- </bean>
- <bean id="hijackBeforeMethod" class="com.kwe.hijack.HijackBeforeMethod"></bean>
- <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <!-- target define which bean you want to hijack -->
- <property name="target" ref="customerService"></property>
- <!-- interceptorNames define which class(advice) you want to apply on this proxy/target object -->
- <property name="interceptorNames">
- <list>
- <value>hijackBeforeMethod</value>
- </list>
- </property>
- </bean>
<property name="interceptorNames"> 中 <value>hijackBeforeMethod</value>代表基于customerService拦截类的是HijackBeforeMethod
执行一下App(把配置文件改成spring-customer2.xml和相关bean),
- public class App2 {
- public static void main(String[] args) {
- ApplicationContext appContext = new ClassPathXmlApplicationContext(
- new String[] { "spring-customer2.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) {
- }
- }
- }
输出为:
- *************************
- HijackBeforeMethod:Before method hijack
- Customer name : yang yang
- *************************
- HijackBeforeMethod:Before method hijack
- Customer website : http://www.youkuaiyun.com
- *************************
- HijackBeforeMethod:Before method hijack
同理,我们想在实体类的方法完成之后再进行操作,则我们可以建立一个HijackAfterMethod实现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 id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <!-- target define which bean you want to hijack -->
- <property name="target" ref="customerService"></property>
- <!-- interceptorNames define which class(advice) you want to apply on this proxy/target object -->
- <property name="interceptorNames">
- <list>
- <value>hijackAfterMethod</value>
- </list>
- </property>
- </bean>
- public class App3 {
- public static void main(String[] args) {
- ApplicationContext appContext = new ClassPathXmlApplicationContext(
- new String[] { "spring-customer3.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) {
- }
- }
- }
执行一下,得到:
- *************************
- Customer name : yang yang
- HijackAfterMethod: After method hijacked!
- *************************
- Customer website : http://www.baidu.com
- HijackAfterMethod: After method hijacked!
- *************************
另外我们想拦截捕获的异常,则可以建立一个HijackThrowException实现ThrowsAdvice接口
- public class HijackThrowException implements ThrowsAdvice{
- public void afterThrowing(IllegalArgumentException e) throws Throwable{
- System.out.println("HijackThrowException:Throw exception hijacked");
- }
- }
配置文件如上,只修改关键字段名字即可,主类的方法也是一样,执行一下看到,在抛出异常的时候就对方法进行了拦截。
- *************************
- Customer name : yang yang
- *************************
- Customer website : http://www.baidu.com
- *************************
- HijackThrowException:Throw exception hijacked
那么我们想对实体类方法执行前和执行后进行拦截,我们要怎么办? ,这个稍微要复杂些....
- /**
- * 集合了方法拦截前后和异常的拦截
- * @author rey.yang
- *
- */
- 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 ThrowAdvice
- System.out.println("HijackArounMethod:Throw exception hijacked!");
- throw e;
- }
- }
- }
配置文件如下:
- <bean id="hijackAroundMethodBean" class="com.kwe.hijack.HijackAroundMethod"></bean>
- <bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <!-- target define which bean you want to hijack -->
- <property name="target" ref="customerService"></property>
- <!-- interceptorNames define which class(advice) you want to apply on this proxy/target object -->
- <property name="interceptorNames">
- <list>
- <value>hijackAroundMethodBean</value>
- </list>
- </property>
- </bean>
执行一下得到
- *************************
- Method name:printName
- Method arguments:[]
- HijackAroundMethod:Before method hijacked!
- Customer name : yang yang
- HijackAroundMethod:Before after hijacked!
- *************************
- Method name:printURL
- Method arguments:[]
- HijackAroundMethod:Before method hijacked!
- Customer website : http://www.baidu.com
- HijackAroundMethod:Before after hijacked!
- *************************
- Method name:printThrowException
- Method arguments:[]
- HijackAroundMethod:Before method hijacked!
- HijackArounMethod:Throw exception hijacked!
在Spring AOP中,应该掌握三种配置方法:Advice,Poingcut,Advisor ,上面的例子是Advice方式进行对方法的拦截。我们可以根据相应的需求进行对应的实现。
原文链接:http://www.mkyong.com/spring/spring-aop-examples-advice/
http://blog.youkuaiyun.com/pearyangyang/article/details/45053913