7.1 AspectJ 基于注解的AOP实现 - 前置通知
指定ISomeService的doFirst()接入点为切入点,并执行前置方法
主业务接口
public interface ISomeService {
void doFirst();
String doSecond(String str);
void doThird();
}
业务实现类
public class SomeServiceImpl implements ISomeService {
@Override
public void doFirst() {
System.out.println("执行doFirst()方法");
}
@Override
public String doSecond(String str) {
System.out.println("执行doSecond()方法");
return str;
}
@Override
public void doThird() {
System.out.println("执行doThird()方法");
}
}
切面
@Aspect //表示当前类为切面
public class MyAspect {
//设置前置方法及切入点
@Before("execution(* *..ISomeService.doFirst(..))")
public void myBefore(JoinPoint jp) {
System.out.println("执行前置方法jp="+jp);
}
}
配置文件
<!-- 注册切面 -->
<bean id="myAspect" class="com.siyantu.annotation.MyAspect"></bean>
<!-- 注册实现类 -->
<bean id="someService" class="com.siyantu.annotation.SomeServiceImpl" />
<!-- aspectj自动代理 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
测试类
public class MyTest {
@Test
public void test() {
String resource = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
ISomeService service = (ISomeService) ac.getBean("someService");
service.doFirst();
System.out.println("=============");
service.doSecond("abcde");
System.out.println("=============");
service.doThird();
System.out.println("=============");
}
}
7.2 AspectJ 基于注解的AOP实现 - 后置通知
@Aspect //表示当前类为切面
public class MyAspect {
...
//设置后置方法及切入点,可以获取目标方法结果,但是因为没有返回值,所以没法修改
@AfterReturning(value="execution(* *..ISomeService.doSecond(..))",returning="result")
public void myAfterReturning(String result) {
System.out.println("执行后置方法 result="+result);
}
}
执行结果:
执行前置方法jp=execution(void com.siyantu.annotation.ISomeService.doFirst())
执行doFirst()方法
=============
执行doSecond()方法
执行后置方法 result=abcde
=============
执行doThird()方法
=============
7.3 AspectJ 基于注解的AOP实现 - 环绕通知
@Aspect //表示当前类为切面
public class MyAspect {
...
//设置环绕通知及切入点
@Around("execution(* *..ISomeService.doSecond(..))")
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("执行环绕通知方法,目标方法执行之前");
//目标方法
Object result = pjp.proceed();
System.out.println("执行环绕通知方法,目标方法执行之后");
if(result != null) {
result = ((String)result).toUpperCase();
}
return result;
}
}
执行结果:
执行前置方法jp=execution(void com.siyantu.annotation.ISomeService.doFirst())
执行doFirst()方法
=============
执行环绕通知方法,目标方法执行之前
执行doSecond()方法
执行环绕通知方法,目标方法执行之后
执行后置方法 result=ABCDE
=============
执行doThird()方法
=============
7.4 AspectJ 基于注解的AOP实现 - 异常通知
异常分两类:
1、运行时异常,不进行处理,也可以通过编译。
若一个类继承自RunTimeException,则该异常就是运行时异常。
2、编译时异常,受查异常,Checked Exception。不进行处理,将无法通过编译。
若一个类继承自Exception,则该类就是受查异常。
自定义异常
主业务接口
public interface ISomeService {
void doThird(String username, String password) throws UserException;
}
业务实现类
public class SomeServiceImpl implements ISomeService {
@Override
public void doThird(String username, String password) throws UserException {
if(!"beijing".equals(username)) {
throw new UsernameException("用户名有误");
}
if(!"111".equals(password)) {
throw new PasswordException("密码有误");
}
}
}
切面
@Aspect //表示当前类为切面
public class MyAspect {
//当目标方法抛出与指定类型的异常具有is-a关系的异常时,执行该异常通知方法
@AfterThrowing(value="execution(* *..ISomeService.doThird(..))",throwing="ex")
public void myAfterThrowing(UsernameException ex) {
System.out.println("发生用户名异常:"+ex.getMessage());
}
@AfterThrowing(value="execution(* *..ISomeService.doThird(..))",throwing="ex")
public void myAfterThrowing(PasswordException ex) {
System.out.println("发生密码异常:"+ex.getMessage());
}
@AfterThrowing(value="execution(* *..ISomeService.doThird(..))",throwing="ex")
public void myAfterThrowing(Exception ex) {
System.out.println("发生其它异常:"+ex.getMessage());
}
}
自定义UserException
public class UserException extends Exception {
public UserException() {
super();
}
public UserException(String message) {
super(message);
}
}
自定义UsernameException
public class UsernameException extends UserException {
public UsernameException() {
super();
// TODO Auto-generated constructor stub
}
public UsernameException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
测试类
异常处理方式一:将异常继续向上抛出,抛给虚拟机
public class MyTest {
@Test
public void test() throws UserException {
String resource = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
ISomeService service = (ISomeService) ac.getBean("someService");
service.doThird("beijing","1112");
}
}
异常处理方式二:捕捉异常,自己处理
public class MyTest {
@Test
public void test() {
String resource = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
ISomeService service = (ISomeService) ac.getBean("someService");
try {
service.doThird("beijing","1112");
} catch (UserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
7.5 AspectJ 基于注解的AOP实现 - 最终通知
切面
@Aspect //表示当前类为切面
public class MyAspect {
//最终通知
@After("execution(* *..ISomeService.doThird(..))")
public void myAfter() {
System.out.println("执行最终通知");
}
}
不管有没有异常,最终通知都会执行
7.6 AspectJ 基于注解的AOP实现 - 定义切入点
@Aspect //表示当前类为切面
public class MyAspect {
//最终通知,使用定义的切入点替代表达式
@After("doThirdPointcut()")
public void myAfter() {
System.out.println("执行最终通知");
}
//定义切入点
@Pointcut("execution(* *..ISomeService.doThird(..))")
public void doThirdPointcut() {}
}