• 第三章 AOP 基于@AspectJ的AOP


    在前面,我们分别使用PointcutAdviceAdvisor接口来描述切点、增强、切面。而现在我们使用@AdpectJ注解来描述。

    在下面的例子中,我们是使用Spring自动扫描和管理Bean。

    http://blog.csdn.net/p_3er/article/details/9239605


    3.6.1一个简单的例子


    a、目标类
    @Repository
    public class UserDaoImpl implements UserDao {
    	public void save() {
    		System.out.println("保存用户...");
    	}
    
    	public void delete() {
    		System.out.println("删除用户...");
    	}
    }

    b、通过一个 POJO使用 @AspectJ管理切面
    /*
     * 通过@Aspect把这个类标识管理一些切面
     */
    @Aspect
    @Component
    public class FirstAspect {	
    
    	/*
    	 * 定义切点及增强类型
    	 */
    	@Before("execution(* save(..))")
    	public void before(){
    		System.out.println("我是前置增强...");
    	}
    }

    c、配置

            配置的时候要引入aop命名空间及打开@AspectJ切面驱动器


    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    	<!—
    驱动器自动为Spring容器中那些匹配@AspectJ切面的Bean创建代理,完成切面积入 
    -->
    	<aop:aspectj-autoproxy/>

    d、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserDao userDao = (UserDao) context.getBean("userDaoImpl");
    		userDao.save();
    		userDao.delete();

    e、结果
    我是前置增强...
    保存用户...
    删除用户...


    3.6.2增强类型及其使用


    @Before前置增强

              @Before(value= "切入点表达式或命名切入点",argNames = "指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔")

              3.6.1中的增强使用:@Before(value="execution(*save(..))")是缺省了value,直接键入值。


    a、目标类

     

    @Service
    public class UserService {
    	public void say(String name){
    		System.out.println("service say:"+name);
    	}
    	
    	public void run(String way){
    		System.out.println("service run:"+way);
    	}
    }


     


    b、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class BeforAspectj {
    	
    /*
    	 *单独配置切点。给切点命名。
    */
    	@Pointcut(value="execution(* say(..)) && args(param)",argNames="param")
    	public void beforePointcut(String param){ }
    	
    	@Before(value="beforePointcut(s)",argNames="s")
    	public void beforeAdvice(String s){
    		System.out.println("beforeAdvice:"+s);
    	}
    }
    

    或者把前面的切点定义那一块直接定义到@Before增强的value中:
    @Aspect
    @Component
    public class BeforAspectj {
    	@Before(value="execution(* say(..)) && args(s)",argNames="s")
    	public void beforeAdvice(String s){
    		System.out.println("beforeAdvice:"+s);
    	}
    }



    c、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    d、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService");
    		service.say("zhangsan");
    		service.run("street");


    e、结果
    beforeAdvice:zhangsan
    service say:zhangsan
    service run:street


    @AfterReturning后置增强

    @AfterReturning(

    value="切入点表达式或命名切入点",

    pointcut="切入点表达式或命名切入点",

    argNames="参数列表参数名",

    returning="目标对象的返回值")

    pointcutvalue是一样的。如果使用pointcut来声明,那么前面声明的value就没用了。


    a、目标类
    @Service
    public class UserService {
    	public void say(String name){
    		System.out.println("service say:"+name);
    	}
    	
    	public void run(String way){
    		System.out.println("service run:"+way);
    	}
    	
    	public String getName(String name){
    		System.out.println("service getName:"+name);
    		return "MR"+name;
    	}
    }

     


    b、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class AfterReturningAspectj {
    	/*
    	 * 即获取返回值,又获取传入的参数
    	 */
    	@AfterReturning(
    			value="execution(* cn.framelife.spring..*.getName(..)) && args(sname)",
    			returning="name",
    			argNames="name,sname")
    	public void afterGetNameAdvice(Object object,String sname){
    		System.out.println("afterGetNameAdvice:"+ (String)object+"--"+sname);
    	}
    	
    	/*
    	 * 只要增强,返回值和参数都不理会
    	 */
    	@AfterReturning(value="execution(* cn.framelife.spring..*.run(..))")
    	public void afterRunAdvice(){
    		System.out.println("afterRunAdvice");
    	}
    }


    c、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    d、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService ");
    		service.getName("zhangsan");
    		service.run("street");



    e、结果
    servicegetName:zhangsan
    afterGetNameAdvice:MRzhangsan--zhangsan
    servicerun:steet
    afterRunAdvice


    @AfterThrowing异常抛出增强、@After Final增强

    @AfterThrowing(

    value="切入点表达式或命名切入点",

    pointcut="切入点表达式或命名切入点",

    argNames="参数列表参数名",

    throwing="异常对应参数名")


    @After( value="切入点表达式或命名切入点",argNames="参数列表参数名")


    @After不管是抛出异常或者是正常退出,该增强都会执行。相当于try-catch-final里的final代码块。


    a、目标类

    @Service
    public class UserService {
    	public void tryThrow(){
    		System.out.println("service tryThrow");
    		throw new RuntimeException("i am a runtime exception");
    	}
    }


     


    b、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class ThrowAspectj {
    	@AfterThrowing(value="execution(* cn.framelife.spring..tryThrow(..))",
    			throwing="exception",
    			argNames="exception")
    	public void afterThrowAdvisor(Exception exception){
    		System.out.println("afterThrowAdvisor:"+exception.getMessage());
    	}
    	
    	@After(value="execution(* cn.framelife.spring..tryThrow(..))")
    	public void finalThrowAdvisor(){
    		System.out.println("finalThrowAdvisor");
    	}
    } 



    c、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    d、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService ");
    		service.tryThrow();



    e、结果
    servicetryThrow
    afterThrowAdvisor:iam a runtime exception
    finalThrowAdvisor
    Exceptionin thread "main" java.lang.RuntimeException:i am a runtime exception


    @Around环绕增强

    @Around( value="切入点表达式或命名切入点",argNames="参数列表参数名")


    a、目标类
    @Service
    public class UserService {
    	public void round(){
    		System.out.println("service round");
    	}
    	
    	public void run(String way){
    		System.out.println("service run:"+way);
    	}
    	
    	public String getName(String name){
    		System.out.println("service getName:"+name);
    		return "MR"+name;
    	}
    }

     


    b、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class AroundAspect {
    	
    	@Around(value="execution(* cn.framelife.spring..round(..))")
    	public Object aroundAdvisor(ProceedingJoinPoint point) throws Throwable{
    		System.out.println("before method");
    		Object target = point.proceed();
    		System.out.println("after method");
    		return target;
    	}
    }



    c、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    d、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService");
    		service.round();
    		service.run("street");





    e、结果
    beforemethod
    serviceround
    aftermethod
    servicerun:street
    afterRunAdvice


    @DeclareParents引介增强

    @DeclareParents(

    value="AspectJ语法类型表达式",

    defaultImpl=引入接口的默认实现类)


    下面的例子是Waiter为目标类,然后让目标类拥有ISeller接口的功能:



    a、两个接口与两个类


     

    目标类与其接口:

     

    public interface IWaiter {
    	public void service();
    }

    @Component
    public class Waiter implements IWaiter {
    	@Override
    	public void service() {
    		System.out.println("service");
    	}
    }

    运行期织入到目标类的功能类与其接口:

    public interface ISeller {
    	public void sell();
    }

    public class Seller implements ISeller {
    	@Override
    	public void sell() {
    		System.out.println("sell");
    	}
    }


    b、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class DeclareAspect {
    
    	/*
    	 * value里面配置目标类
    	 * defaultImpl是功能类的实现类
    	*/
    	@DeclareParents(
    			value="cn.framelife.spring.aspectj.Waiter",
    			defaultImpl=Seller.class)
    	private ISeller seller; //使用功能类接口声明一个对象
    }



    c、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    d、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		IWaiter waiter = (IWaiter) context.getBean("waiter");
    		waiter.service();
    		ISeller seller = (ISeller)waiter;
    		seller.sell();


    e、结果
    service
    sell


    3.6.3切点函数


    @开头的函数都是针对注解类的。而不带@的函数是针对普通类的。


    execution()

    execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)

    除了返回类型模式、方法名模式和参数模式外,其它都是可选的。

    1)通过方法签名定义切点

    execution(public* *(..))

    匹配所有目标类的public方法,但不匹配SmartSellerprotectedvoid showGoods()方法。第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法;


    execution(* *To(..))

    匹配目标类所有以To为后缀的方法。它匹配NaiveWaiterNaughtyWaitergreetTo()serveTo()方法。第一个*代表返回类型,而*To代表任意以To为后缀的方法;


    2)通过类定义切点

    execution(*com.baobaotao.Waiter.*(..))

    匹配Waiter接口的所有方法,它匹配NaiveWaiterNaughtyWaiter类的greetTo()serveTo()方法。第一个*代表返回任意类型,com.baobaotao.Waiter.*代表Waiter接口中的所有方法;


    execution(*com.baobaotao.Waiter+.*(..))

    匹配Waiter接口及其所有实现类的方法,它不但匹配NaiveWaiterNaughtyWaiter类的greetTo()serveTo()这两个Waiter接口定义的方法,同时还匹配NaiveWaiter#smile()NaughtyWaiter#joke()这两个不在Waiter接口中定义的方法。


    3)通过类包定义切点

    在类名模式串中,“.*”表示包下的所有类,而“..*”表示包、子孙包下的所有类。


    execution(*com.baobaotao.*(..))

    匹配com.baobaotao包下所有类的所有方法;


    execution(*com.baobaotao..*(..))

    匹配com.baobaotao包、子孙包下所有类的所有方法,如com.baobaotao.daocom.baobaotao.servier以及com.baobaotao.dao.user包下的所有类的所有方法都匹配。“..”出现在类名中时,后面必须跟“*”,表示包、子孙包下的所有类;


    execution(*com..*.*Dao.find*(..))

    匹配包名前缀为com的任何包下类名后缀为Dao的方法,方法名必须以find为前缀。如com.baobaotao.UserDao#findByUserId()com.baobaotao.dao.ForumDao#findById()的方法都匹配切点。


    4)通过方法入参定义切点

    切点表达式中方法入参部分比较复杂,可以使用“*”和“..”通配符,其中“*”表示任意类型的参数,而“..”表示任意类型参数且参数个数不限。


    execution(*joke(String,int)))

    匹配joke(String,int)方法,且joke()方法的第一个入参是String,第二个入参是int。它匹配NaughtyWaiter#joke(String,int)方法。如果方法中的入参类型是java.lang包下的类,可以直接使用类名,否则必须使用全限定类名,如joke(java.util.List,int)


    execution(*joke(String,*)))

    匹配目标类中的joke()方法,该方法第一个入参为String,第二个入参可以是任意类型,如joke(Strings1,String s2)joke(Strings1,double d2)都匹配,但joke(Strings1,double d2,String s3)则不匹配;


    execution(*joke(String,..)))

    匹配目标类中的joke()方法,该方法第一个入参为String,后面可以有任意个入参且入参类型不限,如joke(Strings1)joke(Strings1,String s2)joke(Strings1,double d2,String s3)都匹配。


    execution(*joke(Object+)))

    匹配目标类中的joke()方法,方法拥有一个入参,且入参是Object类型或该类的子类。它匹配joke(Strings1)joke(Clientc)。如果我们定义的切点是execution(*joke(Object)),则只匹配joke(Objectobject)而不匹配joke(Stringcc)joke(Clientc)

    args()

    该函数的入参是一个类名,表示目标类的方法入参对象是指定的类(包含子类),切点匹配。它允许类后后使用+通配符后缀,但添加也不添加+效果是一样的。



    例子:

    a、一个实体类

    public class User implements Serializable {
    }

    b、目标类
    @Service
    public class UserService {
    	public void say(User user){
    		System.out.println("say");
    	}
    }


    c、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class BeforAspectj {
    	@Before(value="args(cn.framelife.spring.aspectj.User)")
    	public void beforeAdvice(){
    		System.out.println("beforeAdvice");
    	}
    }




    d、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    e、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService");
    		service.say(new User());



    f、结果
    beforeAdvice
    say


    within()

    通过类的匹配模式串声明切点。该函数定义的连接点是针对目标类(不能是接口)而言,而不是针对运行时的对象,这与execution()函数相同。Execution()所指定的连接点可以是小到参数,而within()指定的连接点最小只能是类。

    within(cn.framelife.spring.aspectj.UserService)

    匹配UserService类下所有的方法。

    within(cn.framelife.spring.aspectj.*)

    匹配cn.framelife.spring.aspectj包下所的的类,但不包括子孙包。cn.framelife.spring.aspectj.abc.AbcService是不匹配的。

    within(cn.framelife.spring.aspectj..*)

    匹配cn.framelife.spring.aspectj包及其子孙包下所的的类。

    target()this()

    target()函数是通过判断目标类是否按类型匹配指定类决定连接点是否匹配。

    target(cn.framelife.spring.aspectj.UserService)

    匹配这UserService类及其子孙类的所有方法。如果UserService是一个接口,那么会匹配UserService的实现类及实现类的子孙类中的所有的方法。

     

    this()函数是通过判断代理类是否按类型匹配指定类决定连接点是否匹配。

    一般情况下,使用this()target()定义切点,两者是等效的:

    target(cn.framelife.spring.aspectj.UserService)this(cn.framelife.spring.aspectj.UserService)是一样的。无论UserService是一个类还是一个接口。

    两者区别体现在通过引介切面产生代理对象时。


    @annotation()

    表示标注了某个自定义注解的方法,使用切面。


    例子:

    a、自定义一个方法级别的注解

     

    @Retention(value=RetentionPolicy.RUNTIME)
    @Target(value=ElementType.METHOD)
    public @interface BeforeAdvisor {
    	boolean value() default false;
    }

    b、通过一个 POJO使用 @AspectJ管理切面
    @Aspect
    @Component
    public class BeforAspectj {
    	@Before(value="@annotation(cn.framelife.spring.aspectj.annotation.BeforeAdvisor)")
    	public void beforeAdvice(){
    		System.out.println("beforeAdvice");
    	}
    }


    c、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    d、目标类
    @Service
    public class UserService {
    	@BeforeAdvisor
    	public void annotation(){
    		System.out.println("annotation");
    	}
    }



    e、测试
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService");
    		service.annotation();


    f、结果
    beforeAdvice
    annotation

    @args()

    该函数的入参是一个注解类的类名,表示运行时目标类方法的入参对象的类标注了指定的注解。


    例子:

    a、自定义注解类
    @Retention(value=RetentionPolicy.RUNTIME)
    @Target(value=ElementType.TYPE)
    public @interface UserAnnotation {
    }

    b、切面管理

    @Aspect
    @Component
    public class BeforAspectj {
    	@Before(value="@args(cn.framelife.spring.aspectj.annotation.UserAnnotation)")
    	public void beforeAdvice(){
    		System.out.println("beforeAdvice");
    	}
    }

    c、实体类(使用上面定义的注解)
    @UserAnnotation
    public class User implements Serializable {
    }

    d、目标类
    @Service
    public class UserService {
    	
    	public void annotation(){
    		System.out.println("annotation");
    	}
    	
    	public void say(User user){
    		System.out.println("say");
    	}
    }

    e、配置和3.6.1中一样

    <?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:p="http://www.springframework.org/schema/p"
    	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-3.0.xsd
    		http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop 
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">	
    	<context:component-scan base-package="cn.framelife.spring"></context:component-scan>
    
    	<aop:aspectj-autoproxy/>

    f、测试

     

    ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
    		UserService service = (UserService) context.getBean("userService");
    		service.say(new User());

    g、结果

     

    beforeAdvice
    say


     

    @within@target()

    @winthin(A)匹配任意标注了@A的目标类。@target(A)匹配@A的类及子孙类。


    @annotation是标注在目标类的方法

    @args是标注目标类方法的入参对象的类

    @winthin@target是标注目标类


    注意

    上面的函数(特别是args())除了可以指定类名外,还可以指定参数名,将目标对象连接点上的方法入参绑定到增强的方法中。如:@Before中的例子。


    3.6.4通配符与逻辑运算符


    @Aspectj支持3种通配符:

    *匹配任意字符,但它只能匹配上下文中的一个元素

    ..匹配任意字符,可以匹配上下文中的多个元素,但在表示类时,必须和*联合使用,而在表示入参时则单独使用。

    +表示按类型匹配指定类及其子孙类,必须跟在类名后面。如cn.framelife.spring.UserService+表示UserService类及其子类。


    函数支持:

    支持所有的通配符的函数:execution()within()

    仅支持+通配符的函数:args()this()targ()。虽然这三个函数可以支持+通配符,但对于这些函数来说使用和不使用+都是一样的。

    不支持通配符的函数:@args@within@target()@annotation()。也就是所有用于注解上的函数都不支持通配符。


    @Aspectj支持的逻辑运算符:

    &&

    ||

    !



  • 相关阅读:
    医学影像分割之HIP
    c++画分形之Julia集与Mandelbrot集
    趣题一道
    华山论剑常用角点检测与角点匹配方法比较
    改变鼠标样式
    Unity3D Pro 利用摄像头产生俯视地图效果
    unity3D小地图教程
    WebBrowser网址中特殊字符的问题
    打开多个unity3D项目 (项目多开)
    u3d按住鼠标右键才转动摄像机的方法
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3177807.html
Copyright © 2020-2023  润新知