分享

Spring

 馆天下ccf 2018-03-05

概述

target()切点函数通过判断目标类是否按类型匹配指定类来决定连接点是否匹配. 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;

this()切点函数则通过判断代理类是否按类型匹配指定类来决定是否和切点匹配。 用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配。 this中使用的表达式必须是类型全限定名,不支持通配符。

两者都仅接受类名的入参,虽然类名可以带“+”,但是对于这两个函数来讲,使用或者不是用,效果完全相同。


实例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster


target()

target(M)表示如果目标类按类型匹配于M,这目标类的所有方法都匹配切点。

  • target(com.xgj.IBussiness) :IBussiness为接口,匹配接口实现类中所有方法,包括未在接口中声明的方法
  • target(com.xgj.IBussiness)等同于target(com.xgj.IBussiness+)

这里写图片描述

接口

package com.xgj.aop.spring.advisor.aspectJ.function.target;

public interface IBussinessService {

    String doSomething();

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

目标Bean

package com.xgj.aop.spring.advisor.aspectJ.function.target;

import org.springframework.stereotype.Component;

/**
 * 
 * 
 * @ClassName: BussinessService
 * 
 * @Description: @Component标注的bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午8:18:03
 */

@Component
public class BussinessService {

    public String doSomething() {
        System.out.println("doSomething executed");
        return "success";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

切面

package com.xgj.aop.spring.advisor.aspectJ.function.target;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

/**
 * 
 * 
 * @ClassName: TargetAspect
 * 
 * @Description: @Aspect标注的切面
 *               target(com.xgj.aop.spring.advisor.aspectJ.function.
 *               target.Class1)等同于
 *               target(com.xgj.aop.spring.advisor.aspectJ.function
 *               .target.Class1+)
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午7:53:52
 */

@Aspect
public class TargetAspect {

                @AfterReturning("target(com.xgj.aop.spring.advisor.aspectJ.function.target.IBussinessService)")
    public void crossCuttingCode() {
        System.out.println("some logic is here");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www./schema/beans"
    xmlns:aop="http://www./schema/aop"
    xmlns:xsi="http://www./2001/XMLSchema-instance"
    xmlns:context="http://www./schema/context"
    xsi:schemaLocation="http://www./schema/beans 
        http://www./schema/beans/spring-beans.xsd
        http://www./schema/aop
        http://www./schema/aop/spring-aop.xsd
        http://www./schema/context 
        http://www./schema/context/spring-context.xsd">

<!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.target"/>

<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.target.TargetAspect"/>

</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

测试类

package com.xgj.aop.spring.advisor.aspectJ.function.target;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TargetAspectTest {

    private ApplicationContext applicationContext;

    @Test
    public void test() {
        applicationContext = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/aspectJ/function/target/conf-target.xml");

        BussinessService bussinessService = applicationContext.getBean(
                "bussinessService", BussinessService.class);
        // 织入增强
        bussinessService.doSomething();
        // 织入增强
        bussinessService.doAnother();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

运行结果:

2017-09-05 20:37:52,147  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@285211ef: startup date [Tue Sep 05 20:37:52 BOT 2017]; root of context hierarchy
2017-09-05 20:37:52,264  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/target/conf-target.xml]
doSomething executed
some logic is here
doAnother executed
some logic is here
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

this()

一般情况下,使用this()和target()来匹配定义切点,二者是等效的

  • target(com.xgj.IBussiness)等价于 this(com.xgj.IBussiness)
  • target(com.xgj.BussinessService)等价于this(com.xgj.BussinessService)

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

看个例子:

这里写图片描述

接口

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

public interface IBussinessService {
    String doBussiness();
}
  • 1
  • 2
  • 3
  • 4
  • 5

实现类

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

import org.springframework.stereotype.Component;

/**
 * 
 * 
 * @ClassName: BussinessService
 * 
 * @Description: @Component标注的bean
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午8:18:03
 */

@Component
public class BussinessService implements IBussinessService {

    @Override
    public String doBussiness() {
        System.out.println("doBussiness executed");
        return "success";
    }

    public String doAnother() {
        System.out.println("doAnother executed");
        return "success";
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

另外一个通过引介切面要实现的接口

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

public interface ITransportService {
    public void doTransport();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

实现类

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

public class TransportService implements ITransportService {

    @Override
    public void doTransport() {
        System.out.println("doTransport executed");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

为Bussiness添加 ITransportService接口的切面

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.core.Ordered;

/**
 * 
 * 
 * @ClassName: AddTransportForBussinessAspect
 * 
 * @Description: 为Bussiness添加 ITransportService接口的切面
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午9:18:50
 */

@Aspect
public class AddTransportForBussinessAspect implements Ordered {
    // (1)value 为BussinessService添加接口实现, (2)defaultImpl要添加的接口的默认的接口实现类
    @DeclareParents(value = "com.xgj.aop.spring.advisor.aspectJ.function.thisFun.BussinessService", defaultImpl = TransportService.class)
    public ITransportService iTransportService; // (3) 要实现的目标接口

    @Override
    public int getOrder() {
        return 2;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

横切逻辑切面

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;

/**
 * 
 * 
 * @ClassName: ThisAspect
 * 
 * @Description: @Aspectn标注的切面
 * 
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月5日 下午8:50:26
 */

@Aspect
public class ThisAspect implements Ordered {
    // 织入任何运行期对象为ITransportService的Bean中
    @AfterReturning("this(com.xgj.aop.spring.advisor.aspectJ.function.thisFun.ITransportService)")
    public void corssCuttingCode() {
        System.out.println("some logic is here \n ");
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www./schema/beans"
    xmlns:aop="http://www./schema/aop"
    xmlns:xsi="http://www./2001/XMLSchema-instance"
    xmlns:context="http://www./schema/context"
    xsi:schemaLocation="http://www./schema/beans 
        http://www./schema/beans/spring-beans.xsd
        http://www./schema/aop
        http://www./schema/aop/spring-aop.xsd
        http://www./schema/context 
        http://www./schema/context/spring-context.xsd">

<!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJ.function.thisFun"/>

<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>

<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.thisFun.ThisAspect"/>
<bean class="com.xgj.aop.spring.advisor.aspectJ.function.thisFun.AddTransportForBussinessAspect"/>

</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

测试类

package com.xgj.aop.spring.advisor.aspectJ.function.thisFun;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ThisAspectTest {
    private ApplicationContext applicationContext;

    @Test
    public void test() {
        applicationContext = new ClassPathXmlApplicationContext(
                "classpath:com/xgj/aop/spring/advisor/aspectJ/function/thisFun/conf-this.xml");

        BussinessService bussinessService = (BussinessService) applicationContext
                .getBean("bussinessService");
        // 匹配 this
        bussinessService.doBussiness();
        // 匹配 this
        bussinessService.doAnother();

        // 匹配 this
        ((ITransportService) bussinessService).doTransport();

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

运行结果

2017-09-05 22:24:03,301  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@24177697: startup date [Tue Sep 05 22:24:03 BOT 2017]; root of context hierarchy
2017-09-05 22:24:03,397  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJ/function/thisFun/conf-this.xml]
doBussiness executed
some logic is here 

doAnother executed
some logic is here 

doTransport executed
some logic is here 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

如果有多个切面,注意多切面织入的顺序,如果不加织入的顺序, doTransport 方法的切面无法织入。

可见代理对象的方法都织入了this()函数定义的切面。 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约