aop-annotation
aop说白了就是定义一些常用的切片,但是又不属于某一个类,所以要用切面的方式进行植入,比如日志,事务管理等。
- 首先定义一个切片类(aspect),通知类
- 对谁用,也就是被通知类(无论用xml方式还是注解方式,对被通知的类都没有代码上的影响)
- 在被通知类的哪里用(切点,pointcut)
- 怎么用,定义好多方法,也就是通知
- 什么时候用,就是对应的after,before,aroud(重点是aroud,aroud可以实现切点前后的关系,不想before,after只能固定着用)
- 还能通过aop进行扩展(implement interface)
public interface Member { public void doJob (String message); } public class MemberDaughter implements Member{ public void doJob (String message){ System.out.println("========================= 切入点 ======================="); System.out.println(message + "女儿正在学习"); } } public class MemberSon implements Member{ public void doJob (String message){ System.out.println("========================= 切入点 ======================="); System.out.println(message + "儿子正在打球"); } } public interface Family { public void doSomething (String message); } public class FamilyCui implements Family { private Member member; public FamilyCui(Member member) { this.member = member; } public void doSomething (String message){ member.doJob(message); } }
public interface Outing { public void outing(); } public class OutingImpl implements Outing{ public void outing(){ System.out.println("周末去郊游!"); } }
这个是被通知类和要扩展的类,再定义一个aspect
public class FamilyLog { public void beforFun(String message){ System.out.println("---------- before information ------------"); System.out.println(message); System.out.println("想知道孩子们在干啥!"); } public void afterFun(String message) { System.out.println("---------- after information ------------"); System.out.println(message); System.out.println("孩子们玩完了"); } public void afterReturnFun(String message){ System.out.println("---------- afterReturnFun information ------------"); System.out.println(message); System.out.println("哦,我知道了"); } public void afterThrowingFun(String message){ System.out.println("---------- afterThrowing information ------------"); System.out.println(message); System.out.println("孩子们摔倒了"); } public void aroundFun(ProceedingJoinPoint joinPoint,String message){ try { System.out.println("********** around information ***********"); System.out.println("********** around before information ***********"); System.out.println(message); System.out.println("孩子们摔倒了"); joinPoint.proceed(); System.out.println("********** around after information ***********"); System.out.println("孩子们玩完了"); System.out.println("********** around afterReturnFun information ***********"); System.out.println("哦,我知道了"); } catch (Throwable throwable) { System.out.println("********** around afterThrowing information ***********"); System.out.println("孩子们摔倒了"); throwable.printStackTrace(); } } }
配置一下xml,定义被通知类,切面类,切入点,切入方法<aop:config>。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--family的bean--> <bean id="family" class="spring.in.action.aop.aopTranditional.aop.FamilyCui"> <constructor-arg ref="member" /> </bean> <bean id="member" class="spring.in.action.aop.aopTranditional.aop.MemberDaughter"></bean> <!--aop aspect要用到的类--> <bean id="familyLog" class="spring.in.action.aop.aopTranditional.aspect.FamilyLog"></bean> <!--aop的配置--> <aop:config> <!--用familyLog做aop--> <aop:aspect ref="familyLog"> <!--定义切入点--> <aop:pointcut id="doSomthing" expression="execution(* *.doSomething(..)) and args(message)"/> <!--关联切入点,并指定方法--> <aop:before pointcut-ref="doSomthing" method="beforFun"/> <aop:after pointcut-ref="doSomthing" method="afterFun"/> <aop:after-returning pointcut-ref="doSomthing" method="afterReturnFun"/> <aop:after-throwing pointcut-ref="doSomthing" method="afterThrowingFun"/> <aop:around pointcut-ref="doSomthing" method="aroundFun"/> <aop:declare-parents types-matching="spring.in.action.aop.aopTranditional.aop.Family+" implement-interface="spring.in.action.aop.aopTranditional.interfaceImpl.Outing" default-impl="spring.in.action.aop.aopTranditional.interfaceImpl.OutingImpl"/> </aop:aspect> </aop:config> </beans>
测试类和之行结果
public class TestDiAopSimple { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-tranditional.xml"); Family family = (Family) context.getBean("family"); family.doSomething("这是亲和我的家!"); Outing outing = (Outing)context.getBean("family"); System.out.println("INTERFACE IMPL____________________________"); outing.outing(); } } /Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/bin/java -Didea.launcher.port=7535 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA 14.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath "/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/javafx-doclet.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/lib/tools.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/htmlconverter.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_76.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Users/cuimiao/practice/SpringInAction/spring-in-aciton-bean/target/test-classes:/Users/cuimiao/practice/SpringInAction/spring-in-aciton-bean/target/classes:/Users/cuimiao/.m2/repository/junit/junit/4.12/junit-4.12.jar:/Users/cuimiao/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/cuimiao/.m2/repository/org/springframework/spring-context/4.2.2.RELEASE/spring-context-4.2.2.RELEASE.jar:/Users/cuimiao/.m2/repository/org/springframework/spring-aop/4.2.2.RELEASE/spring-aop-4.2.2.RELEASE.jar:/Users/cuimiao/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar:/Users/cuimiao/.m2/repository/org/springframework/spring-beans/4.2.2.RELEASE/spring-beans-4.2.2.RELEASE.jar:/Users/cuimiao/.m2/repository/org/springframework/spring-expression/4.2.2.RELEASE/spring-expression-4.2.2.RELEASE.jar:/Users/cuimiao/.m2/repository/org/springframework/spring-core/4.2.2.RELEASE/spring-core-4.2.2.RELEASE.jar:/Users/cuimiao/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:/Users/cuimiao/.m2/repository/org/springframework/spring-aspects/4.1.5.RELEASE/spring-aspects-4.1.5.RELEASE.jar:/Users/cuimiao/.m2/repository/org/aspectj/aspectjweaver/1.8.5/aspectjweaver-1.8.5.jar:/Applications/IntelliJ IDEA 14.app/Contents/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cuimiao.test.aop.tranditional.TestDiAopSimple 十一月 29, 2015 11:42:00 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3af1dde3: startup date [Sun Nov 29 23:42:00 CST 2015]; root of context hierarchy 十一月 29, 2015 11:42:00 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-tranditional.xml] ---------- before information ------------ 这是亲和我的家! 想知道孩子们在干啥! ********** around information *********** ********** around before information *********** 这是亲和我的家! 孩子们摔倒了 ========================= 切入点 ======================= 这是亲和我的家!女儿正在学习 ********** around after information *********** 孩子们玩完了 ********** around afterReturnFun information *********** 哦,我知道了 ---------- afterReturnFun information ------------ 这是亲和我的家! 哦,我知道了 ---------- after information ------------ 这是亲和我的家! 孩子们玩完了 INTERFACE IMPL____________________________ 周末去郊游! Process finished with exit code 0
- 但是xml还是太冗余,所以还是用注释
-
public interface Member { public void doJob(String message); } @Component public class MemberDaughter implements Member { public void doJob (String message){ System.out.println("========================= 切入点 ======================="); System.out.println(message + "女儿正在学习"); } } @Component public class MemberSon implements Member { public void doJob (String message){ System.out.println("========================= 切入点 ======================="); System.out.println(message + "儿子正在打球"); } } public interface Family { public void doSomething(String message); } public class FamilyCui implements Family { @Autowired @Qualifier("memberDaughter") private Member member; public FamilyCui() { } public FamilyCui(Member member) { this.member = member; } public void doSomething (String message){ member.doJob(message); } }
定义aspect类,注意这里要定义@Component,因为spring也要扫描这个bean,要不执行不了(才过这个坑)
@Component @Aspect public class FamilyLog { @Pointcut("execution(* *.doSomething(..)) && args(message)") public void family(String message){} @Before("family(message)") public void beforFun(String message){ System.out.println("---------- before information ------------"); System.out.println(message); System.out.println("想知道孩子们在干啥!"); } @After("family(message)") public void afterFun(String message) { System.out.println("---------- after information ------------"); System.out.println(message); System.out.println("孩子们玩完了"); } @AfterReturning("family(message)") public void afterReturnFun(String message){ System.out.println("---------- afterReturnFun information ------------"); System.out.println(message); System.out.println("哦,我知道了"); } @AfterThrowing("family(message)") public void afterThrowingFun(String message){ System.out.println("---------- afterThrowing information ------------"); System.out.println(message); System.out.println("孩子们摔倒了"); } @Around("family(message)") public void aroundFun(ProceedingJoinPoint joinPoint,String message){ try { System.out.println("********** around information ***********"); System.out.println("********** around before information ***********"); System.out.println(message); System.out.println("孩子们摔倒了"); joinPoint.proceed(); System.out.println("********** around after information ***********"); System.out.println("孩子们玩完了"); System.out.println("********** around afterReturnFun information ***********"); System.out.println("哦,我知道了"); } catch (Throwable throwable) { System.out.println("********** around afterThrowing information ***********"); System.out.println("孩子们摔倒了"); throwable.printStackTrace(); } } @DeclareParents(value = "spring.in.action.aop.aopTranditional.aop.Family+", defaultImpl = OutingImpl.class) public static Outing outing; }
定义xml,一定要加上这句(<aop:aspectj-autoproxy>)
还有这句(<context:component-scan base-package:"">)但是 xmlns:context="http://www.springframework.org/schema/context" 这个有坑,有时不对。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="spring.in.action"/> <aop:aspectj-autoproxy/> <bean id="familyAspectAnnotation" class="spring.in.action.aop.aopAnnotation.aop.FamilyCui"> </bean> <!--<bean id="familyAspectj" class="spring.in.action.aop.aopAnnotation.aop.FamilyCui"--> <!--factory-method="aspectOf">--> <!--</bean>--> </beans>
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>spring-bean</groupId> <artifactId>spring-in-aciton-bean</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>spring-in-aciton-bean Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.1.5.RELEASE</version> </dependency> </dependencies> <build> <finalName>spring-in-aciton-bean</finalName> </build> </project>