<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                現在已經知道各部分是如何工作的了, 把他們組合在一起做點有意義的事! 業務服務的執行在并發時可能會失敗(死鎖).如果重試該操作,則很可能在下一輪成功,適用于重試的商業服務(滿足冪等操作,無需返回用戶進行沖突解決,),我們顯示的重試操作,避免客戶端看到`PessimisticLockingFailureException`,這是多個切面建議執行在同一個服務上的. 因為要重試方法,只能采用包圍建議,如下: ~~~java @Aspect public class ConcurrentOperationExecutor implements Ordered { private static final int DEFAULT_MAX_RETRIES = 2; private int maxRetries = DEFAULT_MAX_RETRIES; private int order = 1; public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; } public int getOrder() { return this.order; } public void setOrder(int order) { this.order = order; } @Around("com.xyz.myapp.SystemArchitecture.businessService()") public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { int numAttempts = 0; PessimisticLockingFailureException lockFailureException; do { numAttempts++; try { return pjp.proceed(); } catch(PessimisticLockingFailureException ex) { lockFailureException = ex; } } while(numAttempts <= this.maxRetries); throw lockFailureException; } } ~~~ 注意,切面實現了`Ordered`接口,我們可以設置優先級高于事務建議(每一次的重試都是一次新的事務).通過spring設置參數`maxRetries`和` order`.主要的操作在包圍建議方法`doConcurrentOperation `內.這里是對所有的方法`businessService()`嘗試重試邏輯.每次遇到`PessimisticLockingFailureException `異常會重試執行,知道耗光重試次數. 對應的spring配置: ~~~xml <aop:aspectj-autoproxy/> <bean id="concurrentOperationExecutor" class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor"> <property name="maxRetries" value="3"/> <property name="order" value="100"/> </bean> ~~~ 為了明確切面只是重試冪等操作,可以定義注解`Idempotent `: ~~~java @Retention(RetentionPolicy.RUNTIME) public @interface Idempotent { // marker annotation } ~~~ 實現業務方法需要添加注解`@Idempotent`,切面表達式也需要匹配注解 ~~~java @Around("com.xyz.myapp.SystemArchitecture.businessService() && " + "@annotation(com.xyz.myapp.service.Idempotent)") public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { ... } ~~~ 自己動手寫一個例子: 首先要有一個已存在的業務方法作為連接點,這里是簡單的打印日志 ~~~java import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @Component public class JoinPoint { Logger log = LoggerFactory.getLogger(this.getClass()); public String say(String name) { log.info("hello:{}",name); return "hello" + name; } } ~~~ 然后,定義切面,指定切點表達式和建議執行的位置,這里切點和建議合并寫在一起. 另外一定要注意,要讓切面起作用,切面上的三個注解是必須的 ~~~java import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Aspect @Configuration @EnableAspectJAutoProxy public class BeforeExample { Logger log = LoggerFactory.getLogger(this.getClass()); @Before("execution(* com.ixinnuo.financial.knowledge.aop.JoinPoint.say(..))") public void doAccessCheck(JoinPoint jp) { log.info("BeforeExample... "); Object[] args = jp.getArgs(); for (Object object : args) { log.info("參數{}",args); } } } ~~~ 最后,原來調用業務邏輯的地方,不需要任何改動,正常執行即可 ~~~java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("run") public class RunController { @Autowired private JoinPoint joinPoint; @GetMapping("runAop") @ResponseBody public String runAop(){ joinPoint.say("hanmeimei"); return "ok"; } } ~~~ 下面是輸出的日志信息,對應程序的結構,看出定義的切面已經執行了 ; 注意BeforeExample的代理實例只會創建一次,不會每次調用都創建 ~~~ [2018-07-23 14:15:05.692][INFO][9124-[http-nio-80-exec-1] BeforeExample$$EnhancerBySpringCGLIB$$69278439:20] - BeforeExample... [2018-07-23 14:15:05.693][INFO][9124-[http-nio-80-exec-1] BeforeExample$$EnhancerBySpringCGLIB$$69278439:23] - 參數hanmeimei [2018-07-23 14:15:05.702][INFO][9124-[http-nio-80-exec-1] JoinPoint:13] - hello:hanmeimei ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看