美文网首页Spring FrameWork Core Tech
The IoC Container 5. 使用Spring AO

The IoC Container 5. 使用Spring AO

作者: 小鲍比大爷 | 来源:发表于2019-03-05 09:21 被阅读0次

前面章节讲解过Spring AOP的基本使用和实践,本章以实现AOP事务作为示例,看看如何快速实现一个非常简单的支持事务的Advice实现。
自定义事务注解
只需要将该自定义事务注解注释到需要事务的方法上即可。

package examples;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomTransaction {

}

定义Aspect

package examples;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SystemArchitecture {

    @Pointcut("execution(public * *(..))")
    public void anyPublicOperation() {}

    @Pointcut("@annotation(examples.CustomTransaction) && anyPublicOperation()")
    public void anyMethodUsingTransaction() {}

    @Around("anyMethodUsingTransaction()")
    public void commit(ProceedingJoinPoint pjp) throws Throwable {
        try {
            pjp.proceed();
            doCommit();
        } catch (Throwable throwable) {
            doRollBack();
            throw throwable;
        }
    }

    private void doCommit() {
        System.out.println("commit executed.");
    }

    private void doRollBack() {
        System.out.println("rollback executed.");
    }
}

使用了@Around类型的Advice,它支持在切点周围任意的点插入操作,示例代码commit方法描述了事务控制过程。anyMethodUsingTransaction()代表切入点,切入点是所有的公共方法且该公共方法上是使用examples.CustomTransaction注解的。
定义需要使用事务的服务
使用@CustomTransaction注解到需要事务的方法上。下面给出两个示例:MyCommitService 代表方法执行成功,事务正常提交;MyRollbackService 代表方法执行失败,事务回滚。

package examples;

import org.springframework.stereotype.Component;

@Component
public class MyCommitService {

    @CustomTransaction
    public void writeToDatabase() {
        System.out.println("write data to database...");
    }
}
package examples;

import org.springframework.stereotype.Component;

@Component
public class MyRollbackService {
    @CustomTransaction
    public void writeToDatabase() {
        System.out.println("write data to database...");
        throw new RuntimeException("unknown exception happened!");
    }
}

AppConfig定义

package examples;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = "examples")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
}

入口点函数

package examples;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        MyCommitService myCommitService = context.getBean("myCommitService", MyCommitService.class);
        myCommitService.writeToDatabase();

        MyRollbackService myRollbackService = context.getBean("myRollbackService", MyRollbackService.class);
        myRollbackService.writeToDatabase();
    }
}

执行结果,myCommitService成功提交了事务,myRollbackService由于方法执行抛出异常,导致事务执行回滚操作。

write data to database...
commit executed.
write data to database...
rollback executed.
Exception in thread "main" java.lang.RuntimeException: unknown exception happened!
    at examples.MyRollbackService.writeToDatabase(MyRollbackService.java:10)
    at examples.MyRollbackService$$FastClassBySpringCGLIB$$a9e09160.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88)
    at examples.SystemArchitecture.commit(SystemArchitecture.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
    at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at examples.MyRollbackService$$EnhancerBySpringCGLIB$$c1a15ae7.writeToDatabase(<generated>)
    at examples.Application.main(Application.java:21)

Spring AOP背后实现方式是jdk代理和cglib代理,网上资料很多,有兴趣可以自行查找。

相关文章

网友评论

    本文标题:The IoC Container 5. 使用Spring AO

    本文链接:https://www.haomeiwen.com/subject/ubebuqtx.html