1.重新定义SomeService接口和SomeServiceImpl类
package com.bjpowernode.ba03;
public interface SomeService {
void doSome(String name,Integer age);
String doOther(String name,Integer age);
String doFirst(String name,Integer age);
}
package com.bjpowernode.ba03;
//目标类
public class SomeServiceImpl implements SomeService {
@Override
public void doSome(String name,Integer age) {
//给doSome方法增加一个功能,在doSome()执行之前,输出方法执行的时间
System.out.println("====目标方法doSome()执行====");
}
@Override
public String doOther(String name, Integer age) {
System.out.println("====目标方法doOther()执行====");
return "abcd";
}
@Override
public String doFirst(String name, Integer age) {
System.out.println("====业务方法doFirst()执行====");
return "doFirst";
}
}
2.写切面类
package com.bjpowernode.ba03;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import java.util.Date;
/**
* @Aspect : 是aspectj框架中的注解。
* 作用:表示当前类是切面类。
* 切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
* 位置:在类定义的上面
*/
@Aspect
public class MyAspect {
/**
* 环绕通知方法的定义格式
* 1.public
* 2.必须有一个返回值,推荐使用Object
* 3.方法名称自定义
* 4.方法有参数,固定的参数 ProceedingJoinPoint
*/
/**
* @Around: 环绕通知
* 属性:value 切入点表达式
* 位置:在方法的定义上面
* 特点:
* 1.它是功能最强的通知
* 2.在目标方法的前和后都能增强功能。
* 3.控制目标方法是否被调用执行
* 4.修改原来的目标方法的执行结果。 影响最后的调用结果
*
* 环绕通知,等同于jdk动态代理的,InvocationHandler接口
*
* 参数: ProceedingJoinPoint 就等同于 Method
* 作用:执行目标方法的
* 返回值: 就是目标方法的执行结果,可以被修改。
*
* 环绕通知: 经常做事务, 在目标方法之前开启事务,执行目标方法, 在目标方法之后提交事务
*/
@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAfterReturning(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//实现环绕通知
Object result = null;
System.out.println("环绕通知:在目标方法之前。输出时间:" + new Date());
//1.目标方法调用
result = proceedingJoinPoint.proceed();//method.invoke(); Object result = doFirst();
System.out.println("环绕通知:在目标方法之后,提交事务");
//2.在目标方法前或者后加功能
//返回目标方法的执行结果
return result;
}
}
3.写测试类
package com.bjpowernode;
import com.bjpowernode.ba03.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest03 {
@Test
public void test03(){
String config="applicationContext.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
//从容器中获取目标对象
SomeService proxy = (SomeService) ctx.getBean("someService");
//com.sun.proxy.$Proxy8:jdk动态代理
System.out.println("proxy:"+proxy.getClass().getName());
//通过代理的对象执行方法,实现目标方法执行时,增强了功能
String str = proxy.doFirst("zzh",30);
//System.out.println("str===="+str);
}
}
4.如何控制目标方法是否被执行 ProceedingJoinPoint(继承自JoinPoint)
@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAfterReturning(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取第一个参数
String name = null;
Object args[] = proceedingJoinPoint.getArgs();
if(args != null && args.length >= 1)
{
name = (String)args[0];
}
//实现环绕通知
Object result = null;
System.out.println("环绕通知:在目标方法之前。输出时间:" + new Date());
//1.目标方法调用
if(name.equals("zzh")){
//符合条件。调用目标方法
result = proceedingJoinPoint.proceed();//method.invoke(); Object result = doFirst();
}
System.out.println("环绕通知:在目标方法之后,提交事务");
//2.在目标方法前或者后加功能
//返回目标方法的执行结果
return result;
}
5.修改原来的目标方法的执行结果。 影响最后的调用结果
@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAfterReturning(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//获取第一个参数
String name = null;
Object args[] = proceedingJoinPoint.getArgs();
if(args != null && args.length >= 1)
{
name = (String)args[0];
}
//实现环绕通知
Object result = null;
System.out.println("环绕通知:在目标方法之前。输出时间:" + new Date());
//1.目标方法调用
if(name.equals("zzh")){
//符合条件。调用目标方法
result = proceedingJoinPoint.proceed();//method.invoke(); Object result = doFirst();
}
System.out.println("环绕通知:在目标方法之后,提交事务");
//2.在目标方法前或者后加功能
//返回目标方法的执行结果
if(result != null){
result = "Hello AspectJ";
}
return result;
}