SpringAOP使用个人总结

Spring使用动态代理实现AOP。

注解方式实现AOP

定义一个目标类

@Component
public class CutPointTest{
    public void useHasArg(int arg) {
        System.out.println("useHasArg(),arg:" + arg);
    }

    public void use() {
        System.out.println("use()");
    }
}

定义一个切面

@Component
@Aspect
public class AspectTest {

    //无参切点
    @Pointcut("execution(* com.test.aop.*.use(..))")
    public void usePoint(){}

    //有参切点
    @Pointcut("execution(* com.test.aop.*.useHasArg(int)) && args(arg)")
    public void usePointHasArg(int arg){}

    @Before("usePoint()")
    public void doSomethingBefore(){
        System.out.println("doSomethingBefore");
    }

    @Around("usePoint()")
    public void doSomethingAround(ProceedingJoinPoint joinPoint){
        try {
            System.out.println("doSomethingAround before");
            joinPoint.proceed();
            System.out.println("doSomethingAround after");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    @Before("usePointHasArg(arg)")
    public void doSomethingBeforeHasArg(int arg){
        System.out.println("doSomethingBeforeHasArg,arg:" + arg);
    }
}

主启动类

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        CutPointTest test = (CutPointTest) context.getBean(CutPointTest.class);
        test.use();
        test.useHasArg(3);
    }
}

运行结果:

doSomethingAround before
doSomethingBefore
use()
doSomethingAround after
doSomethingBeforeHasArg,arg:3
useHasArg(),arg:3

需要在xml配置文件中声明

<aop:aspectj-autoproxy/>

上面的方式是为方法提供新功能,下面介绍一下为对象添加新方法(即AOP的引入功能):

定义一个接口

public interface IntroductionInterface {
    public void newMethod();
}

实现类

public class IntroductionImpl implements IntroductionInterface {
    public void newMethod() {
        System.out.println("new Method...");
    }
}

要怎么引入这个接口呢,我们不应该让现有的目标类去实现这个接口,我们的做法应该是新建一个切面,为了简单明了,我们不在新建的切面内做任何通知类型的定义,只使用与引入功能有关的@DeclareParents注解:

@Component
@Aspect
public class NewAspect {
    @DeclareParents(value = "com.test.aop.CutPointTest",defaultImpl = IntroductionImpl.class)
    public static IntroductionInterface introductionInterface;
}

上面表示将接口引入到CutPointTest类,并且声明该接口的实现类为IntroductionImpl

下面是具体调用:

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("applicationContext.xml");
        CutPointTest test = (CutPointTest) context.getBean(CutPointTest.class);
        IntroductionInterface introductionInterface = (IntroductionInterface)test;
        introductionInterface.newMethod();
    }
}

运行结果:

new Method...

这里我们注意到这行代码:

IntroductionInterface introductionInterface = (IntroductionInterface)test;

我们并没有修改CutPointTest类的代码去实现新的接口,但是他的实例却可以转型为新接口类型,而且如果一个类没有实现某个接口是不能转型的,运行时也会抛出ClassCastException,但是现在我们却可以正常运行,我们可以这样简单的理解:spring使用运行时的自动代理模式为我们透明的实现了一个总代理类,我们在访问切点方法的时候其实都是由代理类来处理的,在这里test其实就是总代理类,由于是运行时才确定具体类型,所以我们不要被代码本身迷惑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值