Spring aop 中Aspect的详解与实战例子
Spring aop的的原理:
面向切面的编程,即在预编译和运行期间动态代理方式在不改变现有代码情况下实现某些功能;
Spring aop实现四种方式:
1.经典的基于AOP代理 2.@Aspect注解驱动的界面3.纯POJO切面4.注入式Aspect切面
Spring aop支持5种类型的通知:
1.Before(前) org.apringframework.aop.MethodBeforeAdvice
2.After-returning(返回后) org.springframework.aop.AfterReturningAdvice
3.After-throwing(抛出后) org.springframework.aop.ThrowsAdvice
4.Arround(周围)
org.aopaliance.intercept.MethodInterceptor
5.Introduction(引入)
org.springframework.aop.IntroductionInterceptor
下面对Spring aop 中的Aspect进行实战
首先是2个接口类
package com.zjdelai.emall.horse.web.action.test.aop;
public interface ILoginService {
public boolean loginOut(String userName);
public boolean loginIn(String userName, String password);
}
public interface ILoginService {
public boolean loginOut(String userName);
public boolean loginIn(String userName, String password);
}
package com.zjdelai.emall.horse.web.action.test.aop;
public interface IRegisterService {
public void Register(String userName, String password);
}
public interface IRegisterService {
public void Register(String userName, String password);
}
上面2个接口的实现类
package com.zjdelai.emall.horse.web.action.test.aop.impl;
import org.springframework.stereotype.Service;
import com.zjdelai.emall.horse.web.action.test.aop.ILoginService;
@Service
public class LoginServiceImpl implements ILoginService{
@Override
public boolean loginOut(String userName) {
// TODO Auto-generated method stub
System.out.println("退出成功:login:" + userName);
return false;
}
@Override
public boolean loginIn(String userName, String password) {
// TODO Auto-generated method stub
System.out.println("登录成功:login:" + userName + "," + password);
return false;
}
}
import org.springframework.stereotype.Service;
import com.zjdelai.emall.horse.web.action.test.aop.ILoginService;
@Service
public class LoginServiceImpl implements ILoginService{
@Override
public boolean loginOut(String userName) {
// TODO Auto-generated method stub
System.out.println("退出成功:login:" + userName);
return false;
}
@Override
public boolean loginIn(String userName, String password) {
// TODO Auto-generated method stub
System.out.println("登录成功:login:" + userName + "," + password);
return false;
}
}
package com.zjdelai.emall.horse.web.action.test.aop.impl;
import org.springframework.stereotype.Service;
import com.zjdelai.emall.horse.web.action.test.aop.IRegisterService;
@Service
public class RegisterServiceImpl implements IRegisterService{
@Override
public void Register(String userName, String password) {
// TODO Auto-generated method stub
throw new RuntimeException("优惠券未绑定,强制使用");
}
}
import org.springframework.stereotype.Service;
import com.zjdelai.emall.horse.web.action.test.aop.IRegisterService;
@Service
public class RegisterServiceImpl implements IRegisterService{
@Override
public void Register(String userName, String password) {
// TODO Auto-generated method stub
throw new RuntimeException("优惠券未绑定,强制使用");
}
}
3对上述2个进行注入的类
package com.zjdelai.emall.horse.web.action.test.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LogAspect {
/**
* 此方法记录调用前执行
* @param jp
* @param retVal
*/
@Before("execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))")
public void beforeLog(JoinPoint jp){
System.out.println("此方法记录调用前执行------");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append(";\r\n");
System.out.println(sb.toString());
}
/**
* 记录接口调用后return执行
* @param jp
* @param retVal
*/
@AfterReturning(pointcut="execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))",returning="retVal")
public void afterReturnLog(JoinPoint jp,Object retVal){
System.out.println("记录接口调用后return执行");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append("\r\n您所调用的返回值:"+jp.getSignature().toString()+";\r\n");
System.out.println(sb.toString());
}
/**
* 此方法记录 调用后执行
* @param jp
* @param retVal
*/
@After("execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))")
public void afterLog(JoinPoint jp){
System.out.println("此方法记录调用后执行");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append(";\r\n");
System.out.println(sb.toString());
}
/**
* 此方法记录异常执行
* @param jp
* @param retVal
*/
@AfterThrowing("execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))")
public void afterThrowing(JoinPoint jp){
System.out.println("此方法记录异常执行");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append(";\r\n");
System.out.println(sb.toString());
}
}
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LogAspect {
/**
* 此方法记录调用前执行
* @param jp
* @param retVal
*/
@Before("execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))")
public void beforeLog(JoinPoint jp){
System.out.println("此方法记录调用前执行------");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append(";\r\n");
System.out.println(sb.toString());
}
/**
* 记录接口调用后return执行
* @param jp
* @param retVal
*/
@AfterReturning(pointcut="execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))",returning="retVal")
public void afterReturnLog(JoinPoint jp,Object retVal){
System.out.println("记录接口调用后return执行");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append("\r\n您所调用的返回值:"+jp.getSignature().toString()+";\r\n");
System.out.println(sb.toString());
}
/**
* 此方法记录 调用后执行
* @param jp
* @param retVal
*/
@After("execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))")
public void afterLog(JoinPoint jp){
System.out.println("此方法记录调用后执行");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append(";\r\n");
System.out.println(sb.toString());
}
/**
* 此方法记录异常执行
* @param jp
* @param retVal
*/
@AfterThrowing("execution(* com.zjdelai.emall.horse.web.action.test.aop.impl.*.*(..))")
public void afterThrowing(JoinPoint jp){
System.out.println("此方法记录异常执行");
StringBuffer sb = new StringBuffer();
String className = jp.getTarget().getClass().getName();//获取目标对象对应的类名
String methodName = jp.getSignature().getName();//获取目标对象上正在执行的方法名
sb.append("\r\n您所调用的类名:"+className+";\r\n");
sb.append("\r\n您所调用的方法:"+methodName+";\r\n");
Object[] parames = jp.getArgs();
for(int i=0;i<parames.length;i++){
sb.append("参数名:").append(parames[i]==null?"null":parames[i].toString());
}
sb.append(";\r\n");
System.out.println(sb.toString());
}
}
4下面对上述几个进行配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd" default-autowire="byName">
<bean id="loginService" class="com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl"></bean>
<bean id="registerService" class="com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl"></bean>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="LogAspect" class="com.zjdelai.emall.horse.web.action.test.aop.LogAspect"></bean>
</beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd" default-autowire="byName">
<bean id="loginService" class="com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl"></bean>
<bean id="registerService" class="com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl"></bean>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<bean id="LogAspect" class="com.zjdelai.emall.horse.web.action.test.aop.LogAspect"></bean>
</beans>
5测试类
package com.zjdelai.emall.horse.web.action.content;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.zjdelai.emall.cms.remoting.service.newscontent.INewsContentService;
import com.zjdelai.emall.horse.web.action.BaseHorseAction;
import com.zjdelai.emall.horse.web.action.test.aop.ILoginService;
import com.zjdelai.emall.horse.web.action.test.aop.IRegisterService;
@Controller
public class NewsAction extends BaseHorseAction {
@Autowired
INewsContentService newsContentService;
@Autowired
ILoginService loginService;
@Autowired
IRegisterService registerService;
public void setNewsContentService(INewsContentService newsContentService) {
this.newsContentService = newsContentService;
}
public void setLoginService(ILoginService loginService) {
this.loginService = loginService;
}
public void setRegisterService(IRegisterService registerService) {
this.registerService = registerService;
}
@RequestMapping("/news/list.htm")
public void testAop() {
loginService.loginIn("李俊", "123321");
loginService.loginOut("李俊");
registerService.Register("李俊", "123321");
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.zjdelai.emall.cms.remoting.service.newscontent.INewsContentService;
import com.zjdelai.emall.horse.web.action.BaseHorseAction;
import com.zjdelai.emall.horse.web.action.test.aop.ILoginService;
import com.zjdelai.emall.horse.web.action.test.aop.IRegisterService;
@Controller
public class NewsAction extends BaseHorseAction {
@Autowired
INewsContentService newsContentService;
@Autowired
ILoginService loginService;
@Autowired
IRegisterService registerService;
public void setNewsContentService(INewsContentService newsContentService) {
this.newsContentService = newsContentService;
}
public void setLoginService(ILoginService loginService) {
this.loginService = loginService;
}
public void setRegisterService(IRegisterService registerService) {
this.registerService = registerService;
}
@RequestMapping("/news/list.htm")
public void testAop() {
loginService.loginIn("李俊", "123321");
loginService.loginOut("李俊");
registerService.Register("李俊", "123321");
}
}
6.运行结果
此方法记录调用前执行------
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginIn;
参数名:李俊参数名:123321;
登录成功:login:李俊,123321
记录接口调用后return执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginIn;
参数名:李俊参数名:123321
您所调用的返回值:boolean com.zjdelai.emall.horse.web.action.test.aop.ILoginService.loginIn(String,String);
此方法记录调用后执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginIn;
参数名:李俊参数名:123321;
此方法记录调用前执行------
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginOut;
参数名:李俊;
退出成功:login:李俊
记录接口调用后return执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginOut;
参数名:李俊
您所调用的返回值:boolean com.zjdelai.emall.horse.web.action.test.aop.ILoginService.loginOut(String);
此方法记录调用后执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginOut;
参数名:李俊;
此方法记录调用前执行------
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl;
您所调用的方法:Register;
参数名:李俊参数名:123321;
此方法记录调用后执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl;
您所调用的方法:Register;
参数名:李俊参数名:123321;
此方法记录异常执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl;
您所调用的方法:Register;
参数名:李俊参数名:123321;
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginIn;
参数名:李俊参数名:123321;
登录成功:login:李俊,123321
记录接口调用后return执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginIn;
参数名:李俊参数名:123321
您所调用的返回值:boolean com.zjdelai.emall.horse.web.action.test.aop.ILoginService.loginIn(String,String);
此方法记录调用后执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginIn;
参数名:李俊参数名:123321;
此方法记录调用前执行------
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginOut;
参数名:李俊;
退出成功:login:李俊
记录接口调用后return执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginOut;
参数名:李俊
您所调用的返回值:boolean com.zjdelai.emall.horse.web.action.test.aop.ILoginService.loginOut(String);
此方法记录调用后执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.LoginServiceImpl;
您所调用的方法:loginOut;
参数名:李俊;
此方法记录调用前执行------
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl;
您所调用的方法:Register;
参数名:李俊参数名:123321;
此方法记录调用后执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl;
您所调用的方法:Register;
参数名:李俊参数名:123321;
此方法记录异常执行
您所调用的类名:com.zjdelai.emall.horse.web.action.test.aop.impl.RegisterServiceImpl;
您所调用的方法:Register;
参数名:李俊参数名:123321;
2015-09-16 10:47:28,878 ERROR [com.zjdelai.emall.horse.spring.mvc.servlet.LoggerHandlerExceptionResolver] - exception is handled by HandlerExceptionResolver
java.lang.RuntimeException: 优惠券未绑定,强制使用
java.lang.RuntimeException: 优惠券未绑定,强制使用