本demo简单实现一个切面,首先搭建一个登录的流程,然后定义一个切面对登录动作进行AOP。
Controller:
@Controller
@RequestMapping("/commn/*")
public class LoginController {
@Autowired
private LoginService loginService;
@RequestMapping("login")
public void doLogin(HttpServletRequest request,HttpServletResponse response)throws Exception{
HttpIO httpIO = new HttpIO(request, response);
try {
String userName = httpIO.getParameter("userName");
String psw = httpIO.getParameter("psw");
boolean result = loginService.loginSuccess(userName, psw);
httpIO.setResultFalse();
httpIO.setMsg(result+"");
} catch (Exception e) {
httpIO.setFailedMsg("登录失败", e);
}finally {
httpIO.outAjaxDate();
}
}
}
service:
LoginService.java
public interface LoginService {
public boolean loginSuccess(String userName,String psw);
}
LoginServiceImpl.java
@Service("loginService")
public class LoginServiceImpl implements LoginService{
@Override
public boolean loginSuccess(String userName, String psw) {
System.out.println("loging…………");
int i=0;;
System.out.println(1/i);
return false;
}
}
其实切面很简单,只要在类上面加上@aspect
即可,然后在类的方法上面用@Before、@Around和@After等advice进行标注即可。
切面:
@Component
@Aspect
public class AspectConfig {
@Around("execution(* com.tftDemo.login.service.impl.LoginServiceImpl.login*(String, String))")
public Object loginBefore(ProceedingJoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
Object result = null;
try {
result = joinPoint.proceed();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("begin login:"+joinPoint.getTarget());
return result;
}
@AfterReturning(pointcut="execution(* com.tftDemo..*Impl.login*(..))",returning="rvt")
public Object loginAfter(JoinPoint joinPoint,Object rvt){
System.out.println("login after:"+rvt);
return rvt;
}
}
html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="../commn/login.do">
userName:<input type="text" name="userName">
psw:<input type="text" name="psw">
<input type="submit">
</form>
</body>
</html>
总结:
Spring AOP配置通配符:
Spring AOP 用户可能会经常使用 execution切入点指示符。执行表达式的格式如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外, 所有的部分都是可选的。返回类型模式决定了方法的返回类型必须依次匹配一个连接点。 你会使用的最频繁的返回类型模式是*
,它代表了匹配任意的返回类型。 一个全限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。 你可以使用*
通配符作为所有或者部分命名模式。 参数模式稍微有点复杂:()
匹配了一个不接受任何参数的方法, 而(..)
匹配了一个接受任意数量参数的方法(零或者更多)。 模式(*)
匹配了一个接受一个任何类型的参数的方法。 模式(*,String)
匹配了一个接受两个参数的方法,第一个可以是任意类型, 第二个则必须是String类型。更多的信息请参阅AspectJ编程指南中 语言语义的部分。
通知节点:
@After
| 定义AOP后置通知(不管该方法是否执行成功)
@AfterReturning>
| 在方法成功执行后调用通知
@AfterThrowing
| 在方法抛出异常后调用通知
@Around
| 定义AOP环绕通知
@before
| 定义AOP前置通知