须要的类包:java
一、一个简单的例子spring
package com.yyq.annotation; public interface Waiter { void greetTo(String name); void serveTo(String name); }
NaiveWaiter业务类:数组
package com.yyq.annotation; public class NaiveWaiter implements Waiter { @Override public void greetTo(String name) { System.out.println("NaiveWaiter:greet to " + name + "..."); } @Override public void serveTo(String name) { System.out.println("NaiveWaiter:serving to " + name + "..."); } }
PreGreetingAspect切面实现类:ide
package com.yyq.annotation; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; //经过该注解将PreGreetingAspect标识为一个切面 @Aspect public class PreGreetingAspect { //定义切点和加强类型 @Before("execution(* greetTo(..))") //加强的横切逻辑 public void beforeGreeting(){ System.out.println("How are you"); } }
测试方法:函数
@Test public void aspectJProxyTest(){ Waiter target = new NaiveWaiter(); AspectJProxyFactory factory = new AspectJProxyFactory(); //设置目标对象 factory.setTarget(target); //添加切面对象 factory.addAspect(PreGreetingAspect.class); //生成织入切面的代理对象 Waiter proxy = factory.getProxy(); proxy.greetTo("Anny"); proxy.serveTo("Mei"); }
输出结果:测试
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!--目标Bean--> <bean id="waiter" class="com.yyq.annotation.NaiveWaiter"/> <!--使用了@AspectJ注解的切面类--> <bean class="com.yyq.annotation.PreGreetingAspect"/> <!--自动代理建立器,自动将@AspectJ注解切面类织入到目标Bean中--> <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/> </beans>
测试方法:this
@Test public void aspectJProxyTest2(){ String configPath = "com\\yyq\\annotation\\beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiter"); waiter.greetTo("John"); }
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="waiter" class="com.yyq.annotation.NaiveWaiter"/> <bean class="com.yyq.annotation.PreGreetingAspect"/> </beans>
测试方法:spa
@Test public void aspectJProxyTest3(){ String configPath = "com\\yyq\\annotation\\beans2.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiter"); waiter.greetTo("Herry"); }
Spring支持9个@ApsectJ切点表达式函数,它们用不一样的方式描述目标类的链接点,根据描述对象的不一样,能够将它们大体分为4种类型:
· 方法切点函数:经过描述目标类方法信息定义链接点;
· 方法入参切点函数:经过描述目标类方法入参的信息定义链接点;
· 目标类切点函数:经过描述目标类类型信息定义链接点;
· 代理类切点函数:经过描述目标类的代理类的信息定义链接点; 代理
类别 | 函数 | 入参 | 说明 |
方法切点函数 | execution() | 方法匹配模式串 | 表示知足某一匹配模式的全部目标类方法链接点。如execution(* greetTo(..))表示全部目标类中的greetTo()方法。 |
@annotation() | 方法注解类名 | 表示标注了特定注解的目标方法链接点。如@annotation(com.baobaotao.anno.NeedTest)表示任何标注了@NeedTest注解的目标类方法。 | |
方法入参切点函数 | args() | 类名 | 经过判别目标类方法运行时入参对象的类型定义指定链接点。如args(com.baobaotao.Waiter)表示全部有且仅有一个按类型匹配于Waiter的入参的方法。 |
@args() | 类型注解类名 | 经过判别目标方法的运行时入参对象的类是否标注特定注解来指定链接点。如@args(com.baobaotao.Monitorable)表示任何这样的一个目标方法:它有一个入参且入参对象的类标注@Monitorable注解。 | |
目标类切点函数 | within() | 类名匹配串 | 表示特定域下的全部链接点。如within(com.baobaotao.service.*)表示 com.baobaotao.service包中的全部链接点,也即包中全部类的全部方法,而 within(com.baobaotao.service.*Service)表示在com.baobaotao.service包中,全部以 Service结尾的类的全部链接点。 |
target() | 类名 | 假如目标类按类型匹配于指定类,则目标类的全部链接点匹配这个切点。如经过target(com.baobaotao.Waiter)定义的切点,Waiter、以及Waiter实现类NaiveWaiter中全部链接点都匹配该切点。 | |
@within() | 类型注解类名 | 假如目标类按类型匹配于某个类A,且类A标注了特定注解,则目标类的全部链接点匹配这个切点。如@within(com.baobaotao.Monitorable)定义的切点,假如Waiter类标注了@Monitorable注解,则Waiter以及Waiter实现类NaiveWaiter类的全部链接点都匹配。 | |
@target() | 类型注解类名 | 目标类标注了特定注解,则目标类全部链接点匹配该切点。如@target(com.baobaotao.Monitorable),假如NaiveWaiter标注了@Monitorable,则NaiveWaiter全部链接点匹配切点。 | |
代理类切点函数 | this() | 类名 | 代理类按类型匹配于指定类,则被代理的目标类全部链接点匹配切点。 |
package com.yyq.annotation; public interface Seller { int sell(String goods, String clientName); }
SmartSeller实现类:调试
package com.yyq.annotation; public class SmartSeller implements Seller { public int sell(String goods,String clientName) { System.out.println("SmartSeller: sell "+goods +" to "+clientName+"..."); return 100; } }
EnableSellerAspect切面实现类:
package com.yyq.annotation; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; @Aspect public class EnableSellerAspect { @DeclareParents(value = "com.yyq.annotation.NaiveWaiter",defaultImpl = SmartSeller.class) public Seller seller; }
beans3.xml配置文件:
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="waiter" class="com.yyq.annotation.NaiveWaiter"/> <bean class="com.yyq.annotation.EnableSellerAspect"/> </beans>
测试方法:
@Test public void aspectJProxyTest4(){ String configPath = "com\\yyq\\annotation\\beans3.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter waiter = (Waiter)ctx.getBean("waiter"); waiter.greetTo("John"); Seller seller = (Seller)waiter; //成功进行强制类型转换 seller.sell("Beer","John"); }
package com.yyq.aspectJ; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface NeedTest { boolean value() default true; }
Waiter接口:
package com.yyq.aspectJ; public interface Waiter { void greetTo(String name); void serveTo(String name); }
NaiveWaiter实现类:
package com.yyq.aspectJ; public class NaiveWaiter implements Waiter { @Override public void greetTo(String name) { System.out.println("NaiveWaiter:greet to " + name + "..."); } @Override public void serveTo(String name) { System.out.println("NaiveWaiter:serving to " + name + "..."); } }
NaughtyWaiter实现类:
package com.yyq.aspectJ; public class NaughtyWaiter implements Waiter { @NeedTest public void greetTo(String clientName) { System.out.println("NaughtyWaiter:greet to "+clientName+"..."); } public void serveTo(String clientName){ System.out.println("NaughtyWaiter:serving "+clientName+"..."); } public void joke(String clientName,int times){ System.out.println("NaughtyWaiter:play "+times+" jokes to "+clientName+"..."); } }
TestAspcet切面实现类:
package com.yyq.aspectJ; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; @Aspect public class TestAspect { @AfterReturning("@annotation(com.yyq.aspectJ.NeedTest)") public void needTestFun(){ System.out.println("needTestFun() executed!"); } }
Spring配置自动应用切面:
<?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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:aspectj-autoproxy/> <bean id="naiveWaiter" class="com.yyq.aspectJ.NaiveWaiter"/> <bean id="naughtyWaiter" class="com.yyq.aspectJ.NaughtyWaiter"/> <bean class="com.yyq.aspectJ.TestAspect"/> </beans>
测试方法:
package com.yyq; import com.yyq.aspectJ.Waiter; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AspectJTest { @Test public void annotationAspectJTest() { String configPath = "com\\yyq\\aspectJ\\beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath); Waiter naiveWaiter = (Waiter) ctx.getBean("naiveWaiter"); Waiter naughtyWaiter = (Waiter) ctx.getBean("naughtyWaiter"); naiveWaiter.greetTo("John"); naiveWaiter.serveTo("John"); naughtyWaiter.greetTo("Tom"); naughtyWaiter.serveTo("Tom"); } }
形如within(com.baobaotao.NaiveWaiter)是within()函数所能表达的最小粒度,若是试图用within()匹配方法级别的链接点,如within(com.baobaotao.NaiveWaiter.greet*)将会产生解析错误。
匹配目标类NaiveWaiter的全部方法。若是切点调整为within(com.baobaotao.Waiter),则NaiveWaiter和 NaughtyWaiter中的全部方法都不匹配,而Waiter自己是接口不可能实例化,因此 within(com.baobaotao.Waiter)的声明是无心义的;
匹配com.baobaotao包中的全部类,但不包括子孙包,因此com.baobaotao.service包中类的方法不匹配这个切点;
匹配com.baobaotao包及子孙包中的类,因此com.baobaotao.service、com.baobaotao.dao以及com.baobaotao.service.fourm等包中全部类的方法都匹配这个切点。