public class MyServiceImpl { @Transactional public void method1() { //do something method2(); } @Transactional (propagation=Propagation.REQUIRES_NEW) public void method2() { //do something } }
ãŸããç§ãã¡ã¯çè³¢ããããã¥ã¡ã³ããèªãã§ãå°ãªããšããšãã²ããŒããªãœãã®ã¹ããŒãã®ãããªãèŠãŸãã ãããã£ãŠãç§ãã¡ã¯æ£ããçããç¥ã£ãŠããŸãïŒæ£ãã*ã¯ãç§ãã¡ã«å°ãã人ã®çãã§ãïŒã ãããŠããã®ããã«èãããã¯ãã§ãã
ã Spring AOPã¯ã¢ãããŒã·ã§ã³ãä»ããŠãã©ã³ã¶ã¯ã·ã§ã³ããµããŒãããããã«äœ¿çšããããšããäºå®ã«ãããmethod1ïŒïŒãåŒã³åºããããšããªããžã§ã¯ãã®ãããã·ã¡ãœãããå®éã«åŒã³åºãããŸãã æ°ãããã©ã³ã¶ã¯ã·ã§ã³ãäœæãããMyServiceImplã¯ã©ã¹ã®method1ïŒïŒåŒã³åºããåŒã³åºãããŸãã ãããŠmethod1ïŒïŒããmethod2ïŒïŒãåŒã³åºããšããããã·ãžã®åŒã³åºãã¯ãªããã¯ã©ã¹ã®ã¡ãœãããããã«åŒã³åºããããããæ°ãããã©ã³ã¶ã¯ã·ã§ã³ã¯äœæãããŸãã ã
ããããããªãã¯ãããã©ã®ããã«èµ·ãããç¥ã£ãŠããŸããããªãã¯ãã§ã«é·ãéæ£ããçããç¥ã£ãŠããããã§ãã ãããŠããã®ç¥èãå®æçã«é©çšããŠãã ããã ãããŠãçªç¶...ãããŠçªç¶ãããªãã¯èããŸãïŒã ã¡ãã£ãšåŸ ã£ãŠãã ãããSpringAOPã䜿çšãããšãJDKãä»ããŠãããããCGLIBã䜿çšããŠãããã·ãäœæã§ããããã§ãã ãŸããCTWãŸãã¯LTWãæ¥ç¶ãããŠããå¯èœæ§ããããŸãã ãããŠããã®ãããªçãã¯åžžã«çå®ã§ãããšïŒ ãã
ããã§ã¯ãèå³æ·±ãã§ããïŒ ç¢ºèªããå¿ èŠããããŸãã
å®éããã©ã³ã¶ã¯ã·ã§ã³ã®äœææ¹æ³ã«ã¯èå³ããããŸããã§ããããSpring AOPã¯åžžã«ãããã·ãªããžã§ã¯ããäœæãããããã®ãããã·ãªããžã§ã¯ãã¯äžèšã®åäœãè¡ããšããã¹ããŒãã¡ã³ãã«èå³ããããŸããã æããã«ãJDKåçãããã·ã䜿çšããŠã©ãããŒãäœæããå Žåããã®ã¹ããŒãã¡ã³ãã¯trueã§ãªããã°ãªããŸããã å®éããã®å Žåããªããžã§ã¯ãã¯ã€ã³ã¿ãŒãã§ã€ã¹ã«åºã¥ããŠäœæãããŸãã ãã®ãããªãªããžã§ã¯ãã¯ãããã·ãã¿ãŒã³ã«å®å šã«æºæ ãããã¹ãŠãéåžžã«è«ççã«èŠããŸãã ããããCGLibã¯ç°ãªãã¢ãããŒããåããã¯ã©ã¹ç¶æ¿ãäœæããŸãã ãããŠãããã§ãæ¯ãèããåäžã§ãããã©ããã«çããæ¢ã«å¿ã³èŸŒã¿å§ããŠããŸãã ãã€ã³ãã«å€éšããŒã«ã䜿çšããããšã決å®ãããšããã¹ãŠãããã«èå³æ·±ããã®ã«ãªããŸãã CTWïŒã³ã³ãã€ã«æãŠã£ãŒãã³ã°ïŒããã³LTWïŒããŒãæãŠã£ãŒãã³ã°ïŒã
ãŸããSpring AOPããã¥ã¡ã³ãã®ããã€ãã®å®çŸ©ãããã§è¿œå ããŸãããããã®å®çŸ©ã¯ãæ€èšå¯Ÿè±¡ã®ã³ã³ããã¹ãã§æãèå³æ·±ããã®ã§ãïŒå®éãä»ã®ãã¹ãŠã®å®çŸ©ã¯ãããã¥ã¡ã³ãèªäœã§èŠã€ããããšãã§ããŸãïŒäŸïŒïŒ
ããã§ãå®éšãè¡ãæãåçŽãªãããžã§ã¯ããäœæããŸãã ãããè¡ãã«ã¯ãSpring Bootã䜿çšããŸãã éçºã«ã¯STSã䜿çšããŠããããããã®IDEã®æé ã説æããŸãã ããããæŠããŠãä»ã®ããŒã«ã«ã€ããŠã¯ãã¹ãŠãã»ãŒåãã«ãªããŸãã
- AOPãããã·ïŒã¢ã¹ãã¯ãã³ã³ãã©ã¯ããå®è£ ããããã«AOPãã¬ãŒã ã¯ãŒã¯ã«ãã£ãŠäœæããããªããžã§ã¯ãïŒã¡ãœããã®å®è¡ãªã©ãã¢ããã€ã¹ïŒã Spring Frameworkã§ã¯ãAOPãããã·ã¯JDKåçãããã·ãŸãã¯CGLIBãããã·ã«ãªããŸãã
- ãŠã£ãŒãã³ã°ïŒã¢ã¹ãã¯ããä»ã®ã¢ããªã±ãŒã·ã§ã³ã¿ã€ããŸãã¯ãªããžã§ã¯ããšãªã³ã¯ããŠãã¢ããã€ã¹ããããªããžã§ã¯ããäœæããŸãã ããã¯ãã³ã³ãã€ã«æïŒããšãã°ãAspectJã³ã³ãã€ã©ã䜿çšïŒãããŒãæããŸãã¯å®è¡æã«å®è¡ã§ããŸãã Spring AOPã¯ãä»ã®çŽç²ãªJava AOPãã¬ãŒã ã¯ãŒã¯ãšåæ§ã«ãå®è¡æã«ãŠã£ãŒãã³ã°ãå®è¡ããŸãã
Spring Bootãããžã§ã¯ããäœæãããŠã£ã¶ãŒããèµ·åããŸãïŒFile> New> Spring Starter Projectã ãã©ãŒã ã«å ¥åããŸãã
- åå ïŒAOPTest;
- ã¿ã€ã ïŒMaven;
- å è£ ïŒãžã£ãŒ;
- JavaããŒãžã§ã³ ïŒ8;
- èšèª ïŒJava;
- ã°ã«ãŒã ïŒcom.example.AOPTest;
- ã¢ãŒãã£ãã¡ã¯ã ïŒAOPTest;
- ããã±ãŒãž ïŒcom.example.AOPTestã
æ®ãã¯ããªãã®å¥œã¿ã§ãã [次ãž]ãã¿ã³ãã¯ãªãã¯ããŠãããäžåºŠå ¥åããŸãã
- Spring BootããŒãžã§ã³ ïŒ2.0.0.M7ïŒãããŠããªãã§ããïŒããã¯å·çæç¹ã§å ¥æå¯èœãªææ°ããŒãžã§ã³ã§ãïŒã Spring Bootã®æ¬åœã«è¯ããšããã¯ãæå°éã®åœ¢åŒã§å¿ èŠãªäŸåé¢ä¿ãšå®çŸ©ããã¹ãŠå«ãŸããŠããããšã§ãã Springããäœã䜿çšããããæ£ç¢ºã«ç€ºãå¿ èŠããããŸãã
- åãã¹ãããã§ã䜿çšå¯èœãªäŸåé¢ä¿ã®ãªã¹ãã§ãã¢ã¹ãã¯ãïŒãã£ã«ã¿ãŒã䜿çšã§ããŸãïŒãèŠã€ããŠè¿œå ããŸãã
å®äºãã¯ãªãã¯ããŸãã ã¢ããªã±ãŒã·ã§ã³ã®æºåãã§ããŸããã äœæãããPOMã¯æ¬¡ã®ããã«ãªããŸãã
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.AOPTest</groupId> <artifactId>AOPTest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>AOPTest</name> <description></description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M7</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
å®éããã€ã«ã¹ããŒã³ããŒãžã§ã³ã䜿çšããŠãããããã³ãŒããè¥å¹²å€§ãããªãããªããžããªãžã®ãªã³ã¯ãè¿œå ãããŸãã
ã¢ããªã±ãŒã·ã§ã³ã¯ã©ã¹ãçæãããŸãã
package com.example.AOPTest; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AopTestApplication { public static void main(String[] args) { SpringApplication.run(AopTestApplication.class, args); } }
ç§ãã¡ã®æ³šéïŒç§ãèšã£ãããã«ããã©ã³ã¶ã¯ã·ã§ã³ã«ã¯èå³ããããŸãããããã®ç¶æ³ãã©ã®ããã«æ±ããã«ã€ããŠã¯ã泚éãäœæããŸãïŒïŒ
package com.example.AOPTest; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target(METHOD) public @interface Annotation1 { }
ãããŠã¢ã¹ãã¯ã
package com.example.AOPTest; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class MyAspect1 { @Pointcut("@annotation(com.example.AOPTest.Annotation1)") public void annotated() {} @Before("annotated()") public void printABit() { System.out.println("Aspect1"); } }
@ Annotation1ã¢ãããŒã·ã§ã³ãæã€ã¡ãœããã«ãã€ã³ããããã¢ã¹ãã¯ããå®éã«äœæããŸããã ãã®ãããªã¡ãœãããå®è¡ããåã«ããAspect1ããšããããã¹ããã³ã³ãœãŒã«ã«è¡šç€ºãããŸãã
ã¯ã©ã¹èªäœã«ãComponentãšããŠæ³šéãä»ããããŠããããšã«æ³šæããŠãã ããã ããã¯ãSpringããã®ã¯ã©ã¹ãèŠã€ããŠãããã«åºã¥ããŠBeanãäœæã§ããããã«ããããã«å¿ èŠã§ãã
ããã§ã¯ã©ã¹ãè¿œå ã§ããŸãã
package com.example.AOPTest; import org.springframework.stereotype.Service; @Service public class MyServiceImpl { @Annotation1 public void method1() { System.out.println("method1"); method2(); } @Annotation1 public void method2() { System.out.println("method2"); } }
ç®æšãç®çãããŒã«ã決å®ããŸããã å®éšãéå§ã§ããŸãã
JDKåçãããã·ãšCGLibãããã·
ããã¥ã¡ã³ãã«ç®ãåãããšãããã«æ¬¡ã®ããã¹ãããããŸãã
Spring AOPã¯ãJDKåçãããã·ãŸãã¯CGLIBã䜿çšããŠãç¹å®ã®ã¿ãŒã²ãããªããžã§ã¯ãã®ãããã·ãäœæããŸãã ïŒéžæè¢ãããå Žåã¯ãJDKåçãããã·ãæšå¥šãããŸãïŒãã€ãŸããããã¥ã¡ã³ãã«ãããšãJDKãšCGLibã®äž¡æ¹ã䜿çšããŠãããã·ãªããžã§ã¯ããäœæã§ããŸãããJDKãåªå ããå¿ èŠããããŸãã ãŸããã¯ã©ã¹ã«å°ãªããšã1ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ãããå Žåã䜿çšãããã®ã¯JDKåçãããã·ã§ãïŒãã ããproxy-target-classãã©ã°ãæ瀺çã«èšå®ããããšã§å€æŽã§ããŸãïŒã JDKã䜿çšããŠãããã·ãªããžã§ã¯ããäœæãããšããã¹ãŠã®ã¯ã©ã¹ã€ã³ã¿ãŒãã§ã€ã¹ãšæ°ããåäœãå®è£ ããã¡ãœãããå ¥åã«è»¢éãããŸãã ãã®çµæããããã·ãã¿ãŒã³ãæ£ç¢ºã«å®è£ ãããªããžã§ã¯ããååŸããŸãã ããã¯ãã¹ãŠãBeanã®äœæ段éã§è¡ããããããäŸåæ§æ³šå ¥ãéå§ããããšãå®éã«ã¯ãã®ãããã·ãªããžã§ã¯ããå®è£ ãããŸãã ãããŠããã¹ãŠã®åŒã³åºãã圌ã«è¡ãããŸãã ããããæ©èœã®åœŒã®éšåãå®äºããåŸã圌ã¯ãœãŒã¹ã¯ã©ã¹ã®ãªããžã§ã¯ãã«ç®ãåããŠã圌ã«ã³ã³ãããŒã«ãäžããŸãã ãã®ãªããžã§ã¯ãèªäœãã¡ãœããã®1ã€ã«å€ããå Žåããããã·ãªãã®çŽæ¥åŒã³åºãã«ãªããŸãã å®éããã®ãŸãã«åäœã¯æ£ããçãã«åŸã£ãŠæåŸ ããããã®ã§ãã
ãããã·ãããã¿ãŒã²ãããªããžã§ã¯ããå°ãªããšã1ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããå ŽåãJDKåçãããã·ã䜿çšãããŸãã ã¿ãŒã²ããã¿ã€ãã«ãã£ãŠå®è£ ããããã¹ãŠã®ã€ã³ã¿ãŒãã§ã€ã¹ããããã·ãããŸãã ã¿ãŒã²ãããªããžã§ã¯ããã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããªãå ŽåãCGLIBãããã·ãäœæãããŸãã
CGLIBãããã·ã®äœ¿çšã匷å¶ããå ŽåïŒããšãã°ãã€ã³ã¿ãŒãã§ã€ã¹ã«ãã£ãŠå®è£ ãããã¡ãœããã ãã§ãªããã¿ãŒã²ãããªããžã§ã¯ãã«å¯ŸããŠå®çŸ©ããããã¹ãŠã®ã¡ãœããããããã·ããããïŒãããããããšãã§ããŸãã
CGLIBãããã·ã®äœ¿çšã匷å¶ããã«ã¯ã<aopïŒconfig>èŠçŽ ã®proxy-target-classå±æ§ã®å€ãtrueã«èšå®ããŸã
ããã§ãã¹ãŠãã¯ã£ããããŠããããã«èŠããŸãããCGLibã¯ã©ãã§ããïŒ çµå±ã®ãšãããå®éã«ã¯ãããã·ãªããžã§ã¯ããäœæããã®ã§ã¯ãªããã¯ã©ã¹ã®åå«ãäœæããŸãã ãããŠãããã§ç§ã®è³ã¯ãã§ã«å«ãã§ããŸãïŒãããŠïŒ çµå±ã®ãšãããããã«ã¯ãOOPã«é¢ããæç§æžã®ã»ãã®äžäŸããããŸãã
public class SampleParent { public void method1() { System.out.println("SampleParent.method1"); method2(); } public void method2() { System.out.println("SampleParent.method2"); } } public class SampleChild extends SampleParent { @Override public void method2() { System.out.println("SampleChild.method2"); } }
ããã§ãSampleChildã¯åºæ¬çã«ãããã·ãªããžã§ã¯ãã§ãã ãããŠãããã§ç§ã¯ãã§ã«OOPïŒãŸãã¯ç§ã®ç¥èïŒãããçãå§ããŠããŸãã çµå±ãç¶æ¿ãããå Žåã¯ã芪ã®ä»£ããã«ãªãŒããŒã©ããã¡ãœãããåŒã³åºãå¿ èŠããããJDKãã€ãããã¯ãããã·ã䜿çšãããšãã®åäœãšã¯ç°ãªããŸãã
å¥ã®ãªãã·ã§ã³ããããŸãããããããCGLibã䜿çšããŠãªããžã§ã¯ããäœæããæ¹æ³ã誀解ããŸãããå®éããããã¯ãçžç¶äººãã§ã¯ãªãããäœããã®ãããã·ãã§ããããŸãã ãããŠããã¡ãããå°ãªããšãäœãã確èªããæãç°¡åãªæ¹æ³ã¯ãç°¡åãªäŸã確èªããããšã§ãã ããã§ã¯ãå¥ã®å°ããªãããžã§ã¯ã·ã§ã³ãäœæããŸãããã
ä»åã¯ãSpringã¯ããå¿ èŠãããŸãããæãåçŽãªmavenãããžã§ã¯ããäœæããCGLibãžã®äŸåé¢ä¿ãpomã«è¿œå ããã ãã§ãïŒå®éãããã¯ãã¹ãŠpomãã¡ã€ã«ã®ã³ã³ãã³ãã§ãïŒã
<dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version> </dependency> </dependencies>
2ã€ã®Sampleã¯ã©ã¹ãäœæããããããžã§ã¯ãã«è¿œå ããŸãïŒå¿µã®ãããOOPã®ååã¯çµå±éåããªãããšã確信ãããããïŒãšãã¯ã©ã¹èªäœã«ãã¹ããå®è¡ããmainïŒïŒã¡ãœãããè¿œå ããŸãã
package com.example.CGLIBTest; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLIBTestApp { public static void main(String[] args) { new SampleChild().method1(); System.out.println("//------------------------------------------//"); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleParent.class); enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if(method.getName().equals("method2")) { System.out.println("SampleProxy.method2"); return null; } else { return proxy.invokeSuper(obj, args); } } }); ((SampleParent) enhancer.create()).method1(); } }
æåã®è¡ã§ã¯ãã¯ã©ã¹ã®SampleChildãªããžã§ã¯ãã§method1ïŒïŒãåŒã³åºãïŒå ã»ã©èšã£ãããã«ã念ã®ãã...ïŒããšã³ãã£ã³ãµãŒãäœæããŸãã Enchancerãªããžã§ã¯ãã§ã¯ãmethod2 methodïŒïŒã®åäœããªãŒããŒã©ã€ãããŸãã ãã®åŸãå®éã«ã¯æ°ãããªããžã§ã¯ããäœæããããã®äžã§æ¢ã«method1ïŒïŒãåŒã³åºããŠããŸãã å®è¡ããŸãã
SampleParent.method1 SampleChild.method2 //------------------------------------------// SampleParent.method1 SampleProxy.method2
ãµã...ããªãã¯åãåºãããšãã§ããŸãã åºåã®æåã®2è¡ã«ãããšãéå»20幎éã§PLOã«å€åã¯ãããŸããã
æåŸã®2è¡ã¯ãCGLibãä»ããŠäœæããããªããžã§ã¯ãã§ã¯ãç§ã®ç解ãå®å šã«æ£ããããšã瀺ããŠããŸãã ããã¯æ¬åœã«ç¶æ¿ã§ãã ãããŠããã®ç¬éããããã®æ¹æ³ã§äœæããããªããžã§ã¯ãã¯ãJDKåçãããã·ãªããžã§ã¯ãã匷åãããã®ãšãŸã£ããåãããã«æ©èœããã®ã§ã¯ãªãããšçã£ãŠããŸãã ãããã£ãŠãç§ãã¡ã¯ãã¯ãé 延ããããšãªããå®éšã®ããã«äœæãããããžã§ã¯ããç«ã¡äžããŸãã ãããè¡ãã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã¯ã©ã¹ã«ã©ã³ããŒãè¿œå ããå¿ èŠããããã¯ã©ã¹ã¯æ¬¡ã®åœ¢åŒãåããŸãã
package com.example.AOPTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @SpringBootApplication public class AopTestApplication { @Autowired private MyService myService; public static void main(String[] args) { SpringApplication.run(AopTestApplication.class, args); } @Bean public CommandLineRunner commandLineRunner(ApplicationContext ctx) { return args -> { myService.method1(); }; } }
ããã§ããç§ã¯ãã®Spring Bootã奜ãã§ãããããªããã°ãªããªãããšã¯ãã¹ãŠç§ãã¡ã®ããã«ãã§ã«è¡ãããŠããŸãïŒãã®å°ããªåæ çãªäœè«ãèš±ããŸãïŒã @SpringBootApplicationã¢ãããŒã·ã§ã³ã«ã¯ãSpring Bootã䜿çšããªãã£ãå Žåã«èšè¿°ããå¿ èŠã®ããä»ã®å€ãã®ã¢ãããŒã·ã§ã³ãå«ãŸããŠããŸãã ããã©ã«ãã§ã¯ããã®ã¯ã©ã¹ã«èšå®ãå«ãŸããŠããããšãšããã±ããå ã«ãã³å®çŸ©ãååšãããã©ãããã¹ãã£ã³ããå¿ èŠãããããšããã§ã«ç€ºãããŠããŸãã
åæã«ãããã§æ°ããCommandLineRunner BeanãäœæããŠããŸãããã®Beanã¯ãå®éã«Bean myServiceã§method1ïŒïŒã¡ãœãããåŒã³åºããŸãã
Aspect1 method1 method2
ããŒã...ãã®çµè«ã¯ç§ã«ãšã£ãŠäºæ³å€ã§ããã ã¯ããSpring AOPãJDKåçãããã·ã䜿çšããå ŽåãæåŸ ã«å®å šã«äžèŽããŸãã ããªãã¡ ãµãŒãã¹ã®method1ïŒïŒãåŒã³åºããšãã¢ã¹ãã¯ããæåã«æ©èœãããã®åŸãå¶åŸ¡ãMyServiceImplã¯ã©ã¹ã®ãªããžã§ã¯ãã«è»¢éããããã®ãªããžã§ã¯ãå ã§ããã«åŒã³åºããè¡ãããŸãã
ããããã¯ã©ã¹ã«åäžã®ã€ã³ã¿ãŒãã§ã€ã¹ãæå®ããŸããã§ããã ãããŠããã®å Žåã®Spring AOPã¯CGLibã䜿çšããããšãæåŸ ããŠããŸããã ãã¶ããSpringèªäœãäœããã®åœ¢ã§ãã®å¶éãåé¿ããããã¥ã¡ã³ãã«èšèŒãããŠããããã«ãç¹ã«æå®ããªãéããJDKåçãããã·ãã¡ã€ã³ãªãã·ã§ã³ãšããŠäœ¿çšããããšããŸããïŒ
ã¢ããªã±ãŒã·ã§ã³ã®åŒã³åºãæã«åŒã³åºãã¹ã¿ãã¯ã®å°ãäžã«åº§ã£ãåŸãã€ãŸã Beanãäœæãã段éã§ãå®éã«äœ¿çšããã©ã€ãã©ãªãéžæããå ŽæãèŠã€ããŸããã ããã¯ãDefaultAopProxyFactoryã¯ã©ã¹ãã€ãŸãã¡ãœããã§çºçããŸã
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
ãã®ã¯ã©ã¹ã®Javadocsã¯èšã
ãŸããã¯ã©ã¹ãžã®ã€ã³ã¿ãŒãã§ã€ã¹ã衚瀺ãããªãããã«ããã«ã¯ãhasNoUserSuppliedProxyInterfacesïŒconfigïŒæ¡ä»¶ã確èªããã ãã§ãã ãã®å Žåãtrueãè¿ããŸãã ãããŠãçµæãšããŠãCGLibãä»ãããããã·äœæãåŒã³åºãããŸããDefault AopProxyFactory implementation, creating either a CGLIB proxy or a JDK dynamic proxy.
Creates a CGLIB proxy if one the following is true for a given AdvisedSupport instance:
⢠the optimize flag is set
⢠the proxyTargetClass flag is set
⢠no proxy interfaces have been specified
In general, specify proxyTargetClass to enforce a CGLIB proxy, or specify one or more interfaces to use a JDK dynamic proxy.
èšãæãããšãSpring AOPã¯CGLibã䜿çšããŠBeanã¯ã©ã¹ããç¶æ¿è ãäœæããã ãã§ãªãããã®æ®µéã§æ¬æ Œçãªãããã·ãªããžã§ã¯ãïŒã€ãŸãããããã·ãã¿ãŒã³ã«å¯Ÿå¿ãããªããžã§ã¯ãïŒãå®è£ ããŸãã 圌ããããã©ã®ããã«æ£ç¢ºã«è¡ããã¯ã誰ã§ãèªåã§ç¢ºèªã§ãããã®ã¢ããªã±ãŒã·ã§ã³ã®ãããã°äžã®æé ãå®è¡ã§ããŸãã ç§ã«ãšã£ãŠããéèŠãªããšã¯ãSpringãå éšã§äœ¿çšããŠããã©ã€ãã©ãªãšãŸã£ããéãããªããšããçµè«ã§ããã ãããã«ããã圌ã®è¡åã¯åãã§ãã ãããã«ããããšã³ãããŒãšã³ãããã°ã©ãã³ã°ã®ç·šæã®ããã«ããããã·ãªããžã§ã¯ããäœæãããå®éã«å®éã®ã¯ã©ã¹ãªããžã§ã¯ãã®ã¡ãœãããžã®åŒã³åºããæäŸãããŸãã äžæ¹ãåãã¯ã©ã¹ã®ã¡ãœããããåŒã³åºãããã¡ãœããã¯ãSpring AOPã«ãã£ãŠã€ã³ã¿ãŒã»ããïŒãããã¯ïŒã§ããŸããã
ããã¯ãJDKãšCGLibãä»ããŠäœæããããããã·ã®åäœã®éããæ€çŽ¢ããããšã§åæ¢ã§ããŸãã ããããç§ã®æ¢ç©¶å¿ã¯ãå°ãªããšãããã€ãã®ççŸãèŠã€ããè©Šã¿ãç¶ããŸããã ãããŠããããã·ãªããžã§ã¯ããJDKãä»ããŠäœæãããããã«ããããšã«ããŸããã çè«çã«ã¯ãããã¯åçŽã§ãããå€ãã®æéãè²»ããã¹ãã§ã¯ãããŸããã ããã¥ã¡ã³ãã«æ»ããšããã®ç¹å®ã®ãªãã·ã§ã³ã¯ããã©ã«ãã§äœ¿çšããå¿ èŠãããããšãæãåºãããšãã§ããŸããã1ã€ã®èŠåããããŸãããªããžã§ã¯ãã«ã¯ã€ã³ã¿ãŒãã§ãŒã¹ãå¿ èŠã§ãã ãŸããProxyTargetClassãã©ã°ãã¯ãªã¢ããå¿ èŠããããŸãïŒã€ãŸããfalseïŒã
æåã®æ¡ä»¶ã¯ããããžã§ã¯ãã«é©åãªã€ã³ã¿ãŒãã§ã€ã¹ãè¿œå ããããšã§æºããããŸãïŒãã®ã³ãŒãã¯ãŸã æäŸããŸãããã©ã®ããã«èŠãããã¯ããªãæããã ãšæããŸãïŒã 2çªç®-察å¿ãã泚éãæ§æã«è¿œå ããããšã«ãããã€ãŸã ãã®ãããªãã®
@SpringBootApplication @EnableAspectJAutoProxy(proxyTargetClass = false) public class AopTestApplication {
ãããå®éã«ã¯ããã¹ãŠãããã»ã©åçŽã§ã¯ãªãããšãå€æããŸããã äž¡æ¹ã®ãã§ãã¯-config.isProxyTargetClassïŒïŒããã³hasNoUserSuppliedProxyInterfacesïŒconfigïŒã¯ãŸã trueãè¿ããŸããã ããã§ç§ã¯ãŸã åæ¢ããããšã«ããŸããã ç§ã¯è³ªåã«å¯ŸããåçãåŸãŠããŸããïŒå°ãªããšãSpring 5ã䜿çšããŠããå Žåã¯ïŒããã¥ã¡ã³ãã®äž»åŒµã«ããããããããããã·ãªããžã§ã¯ãã¯CGLibã䜿çšããŠäœæãããå¯èœæ§ãé«ãããšãæãåºããŸããã
ãšããã§ãSpring AOPã«JDKã匷å¶çã«äœ¿çšããæ¹æ³ã誰ããç¥ã£ãŠããå Žåã¯ãã³ã¡ã³ãããåŸ ã¡ããŠããŸãã
ã³ã³ãã€ã«æã®ç¹ããšAspectJ
ããŠãã¢ã¹ãã¯ãã®äžã§ã®ã³ãŒãã®æ¯ãèãã¯ãã©ã®ã©ã€ãã©ãªãå éšã§äœ¿çšããããã«äŸåãããšãã仮説ã¯å€±æããŸããã ãã ããããã¯SpringãAOPã«é¢ããŠæäŸãããã¹ãŠã®å¯èœæ§ã§ã¯ãããŸããã Spring AOPãæäŸããæãèå³æ·±ãïŒç§ã®æèŠã§ã¯ïŒæ©èœã®1ã€ã¯ãAspectJã³ã³ãã€ã©ã䜿çšããæ©èœã§ãã ããªãã¡ ãã¬ãŒã ã¯ãŒã¯ã¯ãã¢ã¹ãã¯ããèšè¿°ããããã«@AspectJã¢ãããŒã·ã§ã³ã䜿çšããå Žåãã©ã³ã¿ã€ã ãŠã£ãŒãã³ã°ããã³ã³ãã€ã«æãŠã£ãŒãã³ã°ã«åãæ¿ããããã«å€æŽãå ããå¿ èŠããªãããã«æžãããŠããŸãã ããã«ïŒSpring Bootã®ãã1ã€ã®å©ç¹ïŒãå¿ èŠãªãã¹ãŠã®äŸåé¢ä¿ãæ¢ã«å«ãŸããŠããŸãã ã³ã³ãã€ã«ãå®è¡ãããã©ã°ã€ã³ã®ã¿ãæ¥ç¶ã§ããŸãã
ãããè¡ãã«ã¯ãpom'nikã«å€æŽãå ããŸãã ãã«ãã»ã¯ã·ã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.10</version> <configuration> <complianceLevel>1.8</complianceLevel> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> <showWeaveInfo>true</showWeaveInfo> <verbose>true</verbose> <Xlint>ignore</Xlint> <encoding>UTF-8 </encoding> <weaveDirectories> <weaveDirectory>${project.build.directory}/classes</weaveDirectory> </weaveDirectories> <forceAjcCompile>true</forceAjcCompile> </configuration> <executions> <execution> <goals> <goal>compile</goal> <!-- <goal>test-compile</goal> --> </goals> </execution> </executions> </plugin> </plugins> </build>
ãã®ãã©ã°ã€ã³ã®æ§æãã©ã¡ãŒã¿ãŒã«ã€ããŠã¯èª¬æããŸããããã¹ãã³ã³ãã€ã«ã®ç®æšãã³ã¡ã³ãã¢ãŠããããçç±ã®ã¿ã説æããŸãã ãããžã§ã¯ãããã«ããããšããã¹ãã®èµ·å段éã§mavenããšã©ãŒã§ã¯ã©ãã·ã¥ããŸããã ã€ã³ã¿ãŒããããä»ããŠå€§éšãããŠãç§ã¯ãã®åé¡ãæ¢ç¥ã§ãããããã解決ããæ¹æ³ãããããšãèŠãŸããã ãã ãããã¹ãã¢ããªã±ãŒã·ã§ã³ã«ã¯ãã¹ãããªããããæãç°¡åãªè§£æ±ºçã¯ãåŒã³åºãããŸã£ããç¡å¹ã«ããããšã§ãïŒåæã«ãã³ã³ãã€ã«ã®æ®µéã§ãã©ã°ã€ã³ãåŒã³åºããŸãïŒã
å®éããããã¯ãã¹ãŠç§ãã¡ãããªããã°ãªããªãã£ãå€æŽã§ãã ã¢ããªã±ãŒã·ã§ã³ãå®è¡ã§ããŸã
Aspect1 Aspect1 method1 Aspect1 Aspect1 method2
ãã®ç¬éãç§ã¯ã¢ã¹ãã¯ãã«å¯Ÿããç§ã®èª€è§£ã®å®å šãªæ·±ããå®æããŸããã ãã¹ãŠã®ã³ãŒããæ°åå確èªããŸããã ã©ãã§äœãééããããé ã®äžã§ã¹ã¯ããŒã«ããããšããŸããã ãããããªããã®ãããªçµæãåŸãããã®ãç解ããŠããŸããã§ããïŒæ£çŽãªãšãããã¯ã©ã¹ã®ã¡ãœãããåŒã³åºãåã«ã¢ã¹ãã¯ãã³ãŒãã2ååŒã³åºãããçç±ã¯æããã§ã¯ãããŸããïŒã
ããã«ãããããããæçµçã«ã¯ããããžã§ã¯ãã¢ã»ã³ããªã®æ®µéã§åä¿¡ãããã°ãèŠãŠæšæž¬ãã次ã®4è¡ãèŠã€ããŸããã
[INFO] Join point 'method-call(void com.example.AOPTest.MyServiceImpl.method1())' in Type 'com.example.AOPTest.AopTestApplication' (AopTestApplication.java:32) advised by before advice from 'com.example.AOPTest.MyAspect1' (MyAspect1.class:19(from MyAspect1.java)) [INFO] Join point 'method-call(void com.example.AOPTest.MyServiceImpl.method2())' in Type 'com.example.AOPTest.MyServiceImpl' (MyServiceImpl.java:12) advised by before advice from 'com.example.AOPTest.MyAspect1' (MyAspect1.class:19(from MyAspect1.java)) [INFO] Join point 'method-execution(void com.example.AOPTest.MyServiceImpl.method1())' in Type 'com.example.AOPTest.MyServiceImpl' (MyServiceImpl.java:10) advised by before advice from 'com.example.AOPTest.MyAspect1' (MyAspect1.class:19(from MyAspect1.java)) [INFO] Join point 'method-execution(void com.example.AOPTest.MyServiceImpl.method2())' in Type 'com.example.AOPTest.MyServiceImpl' (MyServiceImpl.java:17) advised by before advice from 'com.example.AOPTest.MyAspect1' (MyAspect1.class:19(from MyAspect1.java))
ãã¹ãŠãæå®ã®äœçœ®ã«åãŸããŸããã ã³ãŒããã€ã³ãã£ã³ã°ã¯ãã¡ãœãããå®è¡ãããå Žæã ãã§ãªãããããã®åŒã³åºãã®å Žæã§ãçºçããŸããã å®éã®ãšãããSpring AOPã«ã¯ãå®è¡å Žæã§ã®ã¿ã³ãŒãããªã³ã¯ã§ãããšããå¶éããããŸãã ãã®ç¹ã§ã®AspectJã®å¯èœæ§ã¯ã¯ããã«åºãã§ãã äžèŠãªã¢ã¹ãã¯ãã³ãŒã«ã®åé€ã¯éåžžã«ç°¡åã§ããããšãã°ããã®ããã«ã¢ã¹ãã¯ãã³ãŒããå€æŽã§ããŸãã
package com.example.AOPTest; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class MyAspect1 { @Pointcut("execution(public * *(..))") public void publicMethod() {} @Pointcut("@annotation(com.example.AOPTest.Annotation1)") public void annotated() {} @Before("annotated() && publicMethod()") public void printABit() { System.out.println("Aspect1"); } }
ãã®åŸãç§ãã¡ã®çµè«ã¯æåŸ ããã圢ãåããŸãã
Aspect1 method1 Aspect1 method2
ããŠãããã§ç§ãã¡ã®æ£ããçãã¯ãŸã 説æãå¿ èŠã§ãããšèšãããšãã§ããŸããå°ãªããšããåé ã§äžããããã³ãŒãã®äºæ³ãããåäœã«ã€ããŠã€ã³ã¿ãã¥ãŒã§è³ªåãããå Žåãæ確ã«ãã䟡å€ããããŸãããã³ã³ãã€ã«æãã€ã³ãã£ã³ã°ã䜿çšããŠããŸãããïŒå®éãããã¯ã¯ã©ã¹ã³ãŒãã«ã¯ãŸã£ããåæ ãããŠããŸããããpomânikãæäŸããŠããŸããã
ä»ã«äœã«æ³šæãããã§ããã Spring AOPã®ããã¥ã¡ã³ãã«ã¯ããã¹ãŠã®æäœãå®äºããŠãããããæéŠã軜ãæŒããšïŒcïŒå®è¡æãã€ã³ãã£ã³ã°ããã³ã³ãã€ã«æãã€ã³ãã£ã³ã°ã«åãæ¿ããããšãèšèŒãããŠããŸãããããŠããããŸã§èŠãŠããããã«ãããã¯äºå®ã§ããäž¡æ¹ã®ã±ãŒã¹ã®ã³ãŒãã¯åãã§ããïŒå®éãè¡ãããäœæ¥ã¯ãåãã¢ãããŒã·ã§ã³ã®ãã³ãã©ãŒãäœæããã ãã§ã¯ãããŸããã§ããããç§ã¯ããã§æ¢ãŸããŸããã誰ã§ãããã¥ã¡ã³ããèªãã§æå¿ããããšãã§ããŸãïŒã
ãã®ãã¹ãŠã«ã€ããŠãéžæãããã€ã³ãã£ã³ã°ãªãã·ã§ã³ã«ãã£ãŠã¯ãåäœãç°ãªãå ŽåããããŸãïŒäºæããªãå ŽåããããŸãïŒããã§ã«èª¬æããã±ãŒã¹ã«å ããŠãAspectJã³ã³ãã€ã©ãŒã¯Componentã¢ãããŒã·ã§ã³ãå¿ èŠãšããªãããšã«æ³šæããŠãã ãããããªãã¡åé€ãããšãSpring AOPã¯ãã®ãããªBeanãèŠã€ãããããã¢ã¹ãã¯ãã¯é¢ä¿ããŸãããåæã«ãAspectJã³ã³ãã€ã«ã«åãæ¿ãããšããã®ã¢ã¹ãã¯ãã¯æå¹ã«ãªããŸãããã¢ããªã±ãŒã·ã§ã³ã®åäœã¯äºæž¬ã§ããªããªããŸãã
ããŒãã¿ã€ã ãŠã£ãŒãã³ã°
åã®æ®µéã®çµæã«è§ŠçºãããŠãç§ã¯ãã§ã«ç²Ÿç¥çã«æãããã£ãŠããŸãããçµå±ãã³ã³ãã€ã«äžã«ã³ãŒãããã€ã³ããããšãã«ãå®è¡æã«ãªã³ã¯ããããã®åªããåäœãåŸãããå Žåãããããèµ·åæã«ãªã³ã¯ããå ŽåãšåãçµæãæåŸ ãããŸãïŒããã ãšæããŸãïŒããã®ããŒãã«é¢ããããã¥ã¡ã³ãããã£ãšèŠãŠã¿ããšãSpringã®LTWã¯ããã«äœ¿çšã§ããããšãããããŸãããå¿ èŠãªã®ã¯ãæ§æã¯ã©ã¹ã«å¥ã®ã¢ãããŒã·ã§ã³@EnableLoadTimeWeavingãè¿œå ããã ãã§ãã
@SpringBootApplication @EnableLoadTimeWeaving public class AopTestApplication {
ãããããå°ãåã«è¿œå ããpom'nikããaspectj-maven-pluginãåé€ããããšãå¿ããªãã§ãã ããã圌ã¯ããå¿ èŠãããŸããã
ãããŠä»ãããªãã¯èµ°ãããšãã§ããŸã...ããããå®éã«ã¯ããäžã€ã®ãã¥ã¢ã³ã¹ããããŸãã
æ±çšJavaã¢ããªã±ãŒã·ã§ã³
When class instrumentation is required in environments that do not support or are not supported by the existing LoadTimeWeaver implementations, a JDK agent can be the only solution. For such cases, Spring provides InstrumentationLoadTimeWeaver, which requires a Spring-specific (but very general) VM agent,org.springframework.instrument-{version}.jar (previously named spring-agent.jar).
To use it, you must start the virtual machine with the Spring agent, by supplying the following JVM options:
-javaagent:/path/to/org.springframework.instrument-{version}.jar
ãã®ããã¥ã¡ã³ãã«ã¯ãã©ã€ãã©ãªã®ååã§ããspring-instrument- {version} .jarãšããããããªäžæ£ç¢ºãããããŸãããããŠããã®ã©ã€ãã©ãªã¯æ¢ã«ã³ã³ãã¥ãŒã¿ãŒäžã«ãããŸãïŒSpring BootãšMavenã®ãããã§ãïŒãç§ã®å Žåããã®ãã¹ã¯æ¬¡ã®ããã«ãªããŸããcïŒ\ Users \ {MyUserName} .. M2 \ repository \ org \ springframework \ spring-instrument \ 5.0.2.RELEASE \ spring-instrument-5.0.2.RELEASE.jarãç§ã®ããã«ãéçºã«STSã䜿çšããå Žåã¯ã次ã®æé ã«åŸã£ãŠãã ããã ãå®è¡ã>ãå®è¡æ§æãã¡ãã¥ãŒãéããŸã...ããã«Spring Boot Appãããããã®äžã«ã¢ããªã±ãŒã·ã§ã³ã®èµ·åæ§æããããŸãã [åŒæ°]ã¿ããéããŸãã VM argumentsïŒãã£ãŒã«ãã«-javaagentãã©ã¡ãŒã¿ãŒãè¿œå ããŸãïŒcïŒ\ Users \\ {MyUserName} \ãM2 \ repository \ org \ springframework \ spring-instrument \ 5.0.2.RELEASE \ spring-instrument-5.0.2.RELEASE.jarããããŠä»ãç§ãã¡ã¯èµ·åããŸãã
Aspect1 method1 method2
ããŠãåã³ãçµæãæåŸ ããããã§ã¯ãããŸããã LTWãæ¥ç¶ããã®ã¯ãŸã ç°¡åã§ã¯ãªããããããŸããããäœãä»ã®å Žæãèšå®ããå¿ èŠããããããããŸãããç¹°ãè¿ããŸãããèšå®ãæ©èœããããšã確èªãããããã°äžã«ã¢ããªã±ãŒã·ã§ã³ãèµ·åããå®è¡ãããã³ãŒãã確èªããæãç°¡åãªæ¹æ³ã§ããäžèšã®ããã¥ã¡ã³ãã®ã¹ããããã¯ããã®å Žåãã¯ã©ã¹InstrumentationLoadTimeWeaverã䜿çšããå¿ èŠãããããšã瀺ããŠããŸãããŸããBeanãäœæãã段éã§ç¢ºå®ã«åŒã³åºãããã¡ãœããããããŸãã
public void addTransformer(ClassFileTransformer transformer)
ããããã¬ãŒã¯ãã€ã³ãã眮ãå Žæã§ãã
éå§...åæ¢... DefaultAopProxyFactory.createAopProxyïŒïŒã以åã«èšå®ãããã¬ãŒã¯ãã€ã³ãã¯ãJDK察CGLibããœãŒããããŠãããšãã«æ©èœããŸãããåã³éå§ããŸãããä»åã¯äºæ³ãããšããã«åæ¢ããŸããééããªãæ®ã£ãŠããŸãã
ããŠããã®å ŽåãSpring AOPã¯å ã»ã©èŠããã®ãšåããããã·ãªããžã§ã¯ãããã¹ãŠäœæããŸããå¯äžã®éãã¯ããã€ã³ãã£ã³ã°ãå®è¡æ®µéã§ã¯ãªããã¯ã©ã¹ã®ããŒã段éã§è¡ãããããšã§ãããã®ããã»ã¹ã®è©³çŽ°ã«ã€ããŠã¯ãã³ãŒãã§å°ããŸãã
ãããã«
ãŸããç§ãã¡ã®æ£ããçãã¯ãäºçŽã¯ãããã®ã®ã確ãã«æ£ããããã§ãïŒãã³ã³ãã€ã«æã®ç¹ãæ¹ãšAspectJãã®ç« ãåç §ïŒã
åäœã¯ãéžæããããããã·ã¡ã«ããºã ïŒJDKãŸãã¯CGLibïŒã«äŸåããŸããïŒãã¬ãŒã ã¯ãŒã¯ã¯ãå éšã«ãããã®ãçµæã«åœ±é¿ãäžããªãããã«æžãããŠããŸãããŸããLTWæ¥ç¶ã§ãããäœããã®åœ¢ã§åœ±é¿ããããšã¯ãããŸããããŸãã調æ»ããäŸã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ããããã®éãã¯èŠãããŸããã§ãããããã§ããããã¥ã¡ã³ãã«ã¯éãããããšããèšåããããŸãã JDKåçãããã·ã¯ããããªãã¯ã¡ãœããã®ã¿ã«ãªãŒããŒã©ããã§ããŸãã CGLibãããã·-ãããªãã¯ã«å ããŠãä¿è·ãããã¡ãœããããã³ããã±ãŒãžããèŠããããããã£ãŠããã€ã³ãã«ããã«ããããªãã¯ã¡ãœããã®ã¿ãã®å¶éãæ瀺çã«æå®ããªãã£ãå Žåãäºæããªãåäœãçºçããå¯èœæ§ããããŸããçãããå Žåã¯ãCGLibã䜿çšããŠãããã·ãªããžã§ã¯ããçæããããšãã§ããŸãïŒSpringã®æè¿ã®ããŒãžã§ã³ã§ã¯ãããã¯æ¢ã«è¡ãããŠããããã§ãïŒã
Spring AOPã¯ãããã·ããŒã¹ã®ãã¬ãŒã ã¯ãŒã¯ã§ããããã¯ãã¢ã¹ãã¯ãã®ç¯å²å ã«ãããã³ã®ããããã«ãããã·ãªããžã§ã¯ããåžžã«äœæãããããšãæå³ããŸãããããŠãããã¯ã©ã¹ã¡ãœããããå¥ã®ã¯ã©ã¹ã¡ãœãããžã®åŒã³åºããSpring AOPã«ãã£ãŠã€ã³ã¿ãŒã»ããã§ããªãç¬éã¯ãéçºè ã®ééããæ¬ é¥ã§ã¯ãªãããã¬ãŒã ã¯ãŒã¯å®è£ ã®åºç€ãšãªããã¿ãŒã³ã®æ©èœã§ããäžæ¹ãæ€èšäžã®ã±ãŒã¹ã§ã¢ã¹ãã¯ãã³ãŒãã確å®ã«å®è¡ããå¿ èŠãããå Žåã¯ããã®äºå®ãèæ ®ããŠã³ãŒããèšè¿°ããåŒã³åºãããããã·ãªããžã§ã¯ããééããããã«ããå¿ èŠããããŸããããã¥ã¡ã³ãã«ã¯ãããè¡ãæ¹æ³ã®äŸããããŸãããããã§ãæšå¥šãœãªã¥ãŒã·ã§ã³ã§ã¯ãªãããšãçŽæ¥æžãããŠããŸããå¥ã®ãªãã·ã§ã³ã¯ããµãŒãã¹ãããèªäœã«ãæ³šå ¥ãããããšã§ãã Springã®æè¿ã®ããŒãžã§ã³ã§ã¯ããã®ãœãªã¥ãŒã·ã§ã³ã¯æ©èœããŸãã
@Service public class MyServiceImpl{ @Autowired private MyServiceImpl myService; @Annotation1 public void method1() { System.out.println("method1"); myService.method2(); } @Annotation1 public void method2() { System.out.println("method2"); }
確ãã«ããã®ãªãã·ã§ã³ã¯ã¹ã³ãŒãããã·ã³ã°ã«ãã³ãã«çãããã³ã«ã®ã¿é©çšã§ããŸããã¹ã³ãŒããããããã¿ã€ããã«å€æŽãããšããµãŒãã¹ãããèªäœã«æ³šå ¥ããããšãããããã¢ããªã±ãŒã·ã§ã³ãèµ·åã§ããªããªããŸãããã®ããã«ãªããŸã
*************************** APPLICATION FAILED TO START *************************** Description: The dependencies of some of the beans in the application context form a cycle: aopTestApplication (field private com.example.AOPTest.MyServiceImpl com.example.AOPTest.AopTestApplication.myService) âââââââ | myServiceImpl (field private com.example.AOPTest.MyServiceImpl com.example.AOPTest.MyServiceImpl.myService) âââââââ
ä»ã«æ³šç®ãããã®ã¯ãSpring AOPã䜿çšããéã«äŒŽããªãŒããŒãããã§ãããããã·ãªããžã§ã¯ãã¯ãã¢ã¹ãã¯ãã®ç¯å²å ã®ãã³ã®ããããã«åžžã«äœæãããããšãç¹°ãè¿ããŸããããã«ããã³ã®ã€ã³ã¹ã¿ã³ã¹ãæ£ç¢ºã«äœæãããŸãããã®äŸã§ã¯ãã·ã³ã°ã«ãã³Beanãããããèæ ®ãã1ã€ã®ãããã·ãªããžã§ã¯ãã®ã¿ãäœæãããŸããããããã¿ã€ãã䜿çšããŸãããããã·ãªããžã§ã¯ãã®æ°ã¯ãå±éã®æ°ã«å¯Ÿå¿ããŸãããããã·ãªããžã§ã¯ãèªäœã¯ãã¿ãŒã²ãããªããžã§ã¯ãã®ã¡ãœãããåŒã³åºããŸãããããããè¡ãã€ã³ã¿ãŒã»ãã¿ãŒã®ãã§ãŒã³ãå«ãŸããŠããŸããã¿ãŒã²ãããªããžã§ã¯ãã®åç¹å®ã®ã¡ãœãããã¢ã¹ãã¯ãã®åœ±é¿ãåãããã©ããã«é¢ä¿ãªãããã®åŒã³åºãã¯ãããã·ãªããžã§ã¯ããééããŸããããã«ãããã«å ããŠãã¢ã¹ãã¯ãã¯ã©ã¹ã®å°ãªããšã1ã€ã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããŸãïŒãã®äŸã§ã¯ãã€ã³ã¹ã¿ã³ã¹ã¯1ã€ã ãã§ããããããããã¯å¶åŸ¡ã§ããŸãïŒã
ããšãã
èªç¥çäžååã®æèŠã¯ç§ã決ããŠå»ããªãã£ãããã®äŸã®ãã©ã³ã¶ã¯ã·ã§ã³ã«é¢ããäœãã¯ãŸã ééã£ãŠããŸãã圌ã®ã³ãŒããè€è£œããŸãã
public class MyServiceImpl { @Transactional public void method1() { //do something method2(); } @Transactional (propagation=Propagation.REQUIRES_NEW) public void method2() { //do something } }
ããããç解ããŠããããã§ãããããŠãããã¯AOPã ãã§ã¯ãªããããã»ã©å€ããããŸããã1ã€ã®ãã©ã³ã¶ã¯ã·ã§ã³ã®éäžã§å¥ã®ãã©ã³ã¶ã¯ã·ã§ã³ãäœæããå¿ èŠãããçç±ã¯æããã§ã¯ãããŸããïŒå ã ãã®çµæãæ£ç¢ºã«ååŸããããšãæå³ããŠãããšããäºå®ã«åºã¥ããŸãïŒã
å¿ èŠãªãšãã«èª°ããå®éã®ãããžã§ã¯ãã®äŸãæããããšãã§ããã°ãã³ã¡ã³ãã§ãããèŠãŠãããŠæè¬ããŠããŸãã
ããã«ã¯åé¡ã®ã¿ã衚瀺ãããŸãã