spring入门学习-6、AOP几种配置方式详解

spring提供四种各具特色的AOP支持:

①基于代理的经典AOP(利用ProxyFactoryBean进行XML配置,这种做法spring2.0以前常用配置)

②Schema-based的AOP(利用<aop:config>)

③@ASpectJ注解驱动的AOP

④注入式AspectJ的AOP(其实与Spring并无多大的关系,这个就是使用AspectJ这个框架实现Aop编程)

下面我们对前三种类型分别进行介绍。

 

  • 基于代理的经典AOP

这种方式是使用ProxyFactoryBean来创建的,下面对几个主要的类进行概要说明:

按方法名字匹配:org.springframework.aop.support.NameMatchMethodPointcut 成员变量:mappedNames匹配方法名集合

前置通知:org.springframework.aop.MethodBeforeAdvice

后置通知:org.springframework.aop.AfterReturningAdvice

环绕通知:org.aopalliance.intercept.MethodInterceptor (这个依赖于aopalliance-1.0.jar这个包)

异常通知:org.springframework.aop.ThrowsAdvice

 

ProxyFactoryBean使用时有以下几方面需要注意:

被代理的类没有实现任何接口,使用CGlib代理,否则使用JDK代理。

通过设置proxyTargetClass为true,可强制使用CGlib代理。

如果目标类实现一个或者多个接口,那么创建代理的类型将依赖ProxyFactoryBean的配置,XML文件中使用proxyInterfaces属性设置。

如果ProxyFactoryBean的proxyInterfaces属性设置了接口,那么这个将采用JDK代理,如果没有设置接口,但是目标类实现了一个或多个接口,那么ProxyFactoryBean会自动检测,并创建一个基于JDK的代理。

 

具体例子如下:

IStudentService

public interface IStudentService {
    public void save();
}

 

StudentServiceImpl

public class StudentServiceImpl implements IStudentService {
    @Override
    public void save() {
        System.out.println("添加成功.....");
    }
}

 

StudentBeforeAdvice 前置通知):

public class StudentBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("StudentBeforeAdvice : " + method.getName() + target.getClass().getSimpleName());
    }
}

 

StudentAfterAdvice 后置通知):

public class StudentAfterAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnVal, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("StudentAfterAdvice :" + method.getName() +"  "+target.getClass().getSimpleName() +"  " + returnVal);
    }
}

 

StudentMethodInterceptor 环绕通知):

public class StudentMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("StudentMethodInterceptor1 :" + invocation.getMethod().getName() +"  "+invocation.getStaticPart().getClass().getSimpleName());
        Object obj = invocation.proceed();
        System.out.println("StudentMethodInterceptor2 " + obj);
        return obj;
    }
}

 

StudentThrowAdvice 异常通知):

/**
 * 实现ThrowsAdvice,只是一个标记,需要我们定义afterThrowing方法
 */
public class StudentThrowAdvice implements ThrowsAdvice {
    public void afterThrowing(Method method,Object[] args,Object target,Exception ex){
        System.out.println("StudentThrowAdvice :" + method.getName()+"  "+target.getClass().getSimpleName() );
    }
}

 

测试方法:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-api.xml");
        IStudentService studentServicet = (IStudentService) context.getBean("studentServiceImpl");
        studentServicet.save();
    }
}

 

配置文件有以下几种方式:

①针对每个类都配置通知

<bean id="studentBeforeAdvice" class="com.base.java.aop.api.StudentBeforeAdvice"></bean>
<bean id="studentAfterAdvice" class="com.base.java.aop.api.StudentAfterAdvice"></bean>
<bean id="studentThrowAdvice" class="com.base.java.aop.api.StudentThrowAdvice"></bean>
<bean id="studentMethodInterceptor" class="com.base.java.aop.api.StudentMethodInterceptor"></bean>
<bean id="studentServiceImplTarget" class="com.base.java.aop.api.StudentServiceImpl"></bean>
<bean id="studentServiceImpl" class="org.springframework.aop.framework.ProxyFactoryBean">

<!--此处可以指定该类实现接口也可以不指定,不指定ProxyFactoryBean自动查找
<property name="proxyInterfaces">
    <value>com.base.java.aop.api.IStudentService</value>
</property>-->
    <property name="target">
        <ref bean="studentServiceImplTarget"/>
    </property>
    <property name="interceptorNames">
        <list>

  <value>studentBeforeAdvice</value>
            <value>defaultAdvisor</value>
            <value>studentAfterAdvice</value>
            <value>studentMethodInterceptor</value>
            <value>studentThrowAdvice</value>
        </list>
    </property>
</bean>

 

②利用DefaultPointcutAdvisor配置通知,但是这种方式只能配置一个pointcut和一种通知

<bean id="studentBeforeAdvice" class="com.base.java.aop.api.StudentBeforeAdvice"></bean>
<bean id="studentAfterAdvice" class="com.base.java.aop.api.StudentAfterAdvice"></bean>
<bean id="studentThrowAdvice" class="com.base.java.aop.api.StudentThrowAdvice"></bean>
<bean id="studentMethodInterceptor" class="com.base.java.aop.api.StudentMethodInterceptor"></bean>
<bean id="studentServiceImplTarget" class="com.base.java.aop.api.StudentServiceImpl"></bean>
<bean id="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
    <property name="mappedNames">
        <list>
            <value>sa*</value>
        </list>
    </property>
</bean>
<bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
    <property name="advice" ref="studentBeforeAdvice"/>
    <property name="pointcut" ref="pointcutBean"/>
</bean>

<bean id="studentServiceImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <ref bean="studentServiceImplTarget"/>
    </property>
    <property name="interceptorNames">
        <list>
            <value>defaultAdvisor</value>
            <value>studentAfterAdvice</value>
            <value>studentMethodInterceptor</value>
            <value>studentThrowAdvice</value>
        </list>
    </property>
</bean>

 

③使用匿名的内部Bean来隐藏目标和代理之间的区别

<bean id="studentBeforeAdvice" class="com.base.java.aop.api.StudentBeforeAdvice"></bean>
<bean id="studentAfterAdvice" class="com.base.java.aop.api.StudentAfterAdvice"></bean>
<bean id="studentThrowAdvice" class="com.base.java.aop.api.StudentThrowAdvice"></bean>
<bean id="studentMethodInterceptor" class="com.base.java.aop.api.StudentMethodInterceptor"></bean>
<bean id="studentServiceImpl" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <bean class="com.base.java.aop.api.StudentServiceImpl"></bean>
    </property>
    <property name="interceptorNames">
        <list>

  <value>studentBeforeAdvice</value>
            <value>defaultAdvisor</value>
            <value>studentAfterAdvice</value>
            <value>studentMethodInterceptor</value>
            <value>studentThrowAdvice</value>
        </list>
    </property>
</bean>

 

④简化Porxy定义

<bean id="studentBeforeAdvice" class="com.base.java.aop.api.StudentBeforeAdvice"></bean>
<bean id="studentAfterAdvice" class="com.base.java.aop.api.StudentAfterAdvice"></bean>
<bean id="studentThrowAdvice" class="com.base.java.aop.api.StudentThrowAdvice"></bean>
<bean id="studentMethodInterceptor" class="com.base.java.aop.api.StudentMethodInterceptor"></bean>
<bean id="studentServiceImplTarget" class="com.base.java.aop.api.StudentServiceImpl"></bean>
<bean id="baseProxyBean" class="org.springframework.aop.framework.ProxyFactoryBean"
      lazy-init="true" abstract="true"></bean>

<bean id="studentServiceImpl"  parent="baseProxyBean">
    <property name="target">
        <bean class="com.base.java.aop.api.StudentServiceImpl"></bean>
    </property>
    <property name="proxyInterfaces">
        <value>com.base.java.aop.api.IStudentService</value>
    </property>
    <property name="interceptorNames">
        <list>
            <value>studentBeforeAdvice</value>
            <value>studentAfterAdvice</value>
            <value>studentMethodInterceptor</value>
            <value>studentThrowAdvice</value>
        </list>
    </property>
</bean>

 

⑤基于BeanNameAutoProxyCreator自动代理

<bean id="studentBeforeAdvice" class="com.base.java.aop.api.StudentBeforeAdvice"></bean>
 <bean id="studentAfterAdvice" class="com.base.java.aop.api.StudentAfterAdvice"></bean>
 <bean id="studentThrowAdvice" class="com.base.java.aop.api.StudentThrowAdvice"></bean>
 <bean id="studentMethodInterceptor" class="com.base.java.aop.api.StudentMethodInterceptor"></bean>
 <bean id="studentServiceImpl" class="com.base.java.aop.api.StudentServiceImpl"></bean>

 <!--配置自动代理-->
 <!--配置基于BeanNameAutoProxyCreator类的自动代理-->
 <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
     <!--配置作用于的bean,也就是筛选BeanName以配置文件中<bean> id为准-->
     <property name="beanNames" value="*Impl"></property>
     <!--配置增强处理-->
     <property name="interceptorNames">
         <list>
             <value>studentBeforeAdvice</value>
             <value>studentAfterAdvice</value>
             <value>studentMethodInterceptor</value>
             <value>studentThrowAdvice</value>
         </list>
     </property>
 </bean>

 

⑥基于DefaultAdvisorAutoProxyCreator自动代理

这个自动代理可以指定切面切入点和BeanNameAutoProxyCreator的区别是BeanNameAutoProxyCreator针对的是类。

<bean id="studentBeforeAdvice" class="com.base.java.aop.api.StudentBeforeAdvice"></bean>
 <bean id="studentServiceImplTarget" class="com.base.java.aop.api.StudentServiceImpl"></bean>
 <!--配置切面-->
 <bean id="myAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
     <property name="pattern" value=".*save"></property><!--对切入点进行过滤-->
     <property name="advice" ref="studentBeforeAdvice"></property>
 </bean>
 <!--基于切面信息来产生自动代理-->
 <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

 

  • Schema-based的AOP

①AOP配置元素说明:

AOP 配置元素

描述

aop : advisor

定义 AOP 通知器

aop : after

定义 AOP 后置通知(不管被通知方法是否执行成功)

aop : after-returing

定义 AOP after-returing 通知

aop : after-throwing

定义 AOP after-throwing 通知

aop : around

定义 AOP 环绕通知

aop : aspect

定义切面

aop : aspectj-autoproxy

启动 @AspectJ 注解驱动的切面

aop : before

定义 AOP 前置通知

aop : config

顶层的 AOP 配置元素,大多数 aop : * 元素必须包含在 元素内

aop : declare-parents

为被通知的对象引入额外接口,并透明的实现

aop : pointcut

定义切点

 

②Expression举例说明:

表达式

描述

execution(public * *(..))

任意公共方法的执行

execution(* set*(..))

任何一个以“set”开始的方法

execution(* com.xyz.service.AccountService.*(..))

AccountService 接口的任意方法的执行

execution(* com.xyz.service.*.*(..))

定义在service包里的任意方法的执行

execution(* com.xyz.service..*.*(..))

定义在service包和所有子包里的任意类的任意方法

execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")

定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法

within(com.xys.*)

包中的所有类的所有方法. 

within(com.xys.service.*Service)

表示在 com.xys.service 包中所有以 Service 结尾的类的所有的连接点

bean(*Service)

匹配以指定名字结尾的 Bean 中的所有方法

bean(*Service) && within(com.xys.service.*)

匹配名字以 Service 结尾, 并且在包 com.xys.service 中的 bean

this(com.test.spring.aop.pointcutexp.MyInterface)

实现了MyInterface接口的所有类,如果MyInterface不是接口,限定MyInterface单个类

args

 

......

......

 

target、this、within的区别

target匹配目标对象的类型,即被代理对象的类型,例如A继承了B接口,则使用target("B"),target("A")均可以匹配到A

this匹配的是代理对象的类型,例如存在一个接口B,使用this("B"),如果某个类A的JDK代理对象类型为B,则A实现的接口B的方法会作为切点进行织入。

within比较严格,它是严格匹配被代理对象类型的,不会理会继承关系,例如A继承了接口B,则within("B")不会匹配到A,但是within("B+")可以匹配到A

 

<aop:config>风格的配置大量的使用了Spring的自动代理机制。

 

③具体例子:

AspectBiz

public class AspectBiz {
    public void save(){
        System.out.println("调用方法................");
    }

    public void init(String name,int times){
        System.out.println("调用init....");
    }
}

 

MoocAspect

public class MoocAspect {
    public void before(){
        System.out.println("MoocAspect.before....");
    }
    public void afterReturning(){
        System.out.println("MoocAspect.afterReturning.....");
    }
    public void afterThrowing(){
        System.out.println("MoocAspect.afterThrowing...");
    }
    public void after(){
        System.out.println("MoocAspect.after...");
    }

    /**
     * 环绕通知第一个参数必须是ProceedingJoinPoint
     * @param pre
     * @throws Throwable
     */
    public void around(ProceedingJoinPoint pre) throws Throwable {
        System.out.println("MoocAspect.around1....");
        pre.proceed();
        System.out.println("MoocAspect.around2....");
    }

    public void aroundInit(ProceedingJoinPoint pre,String name,int times) throws Throwable {
        System.out.println("MoocAspect.aroundInit : " + name + times);
        System.out.println("MoocAspect.aroundInit1....");
        pre.proceed();
        System.out.println("MoocAspect.aroundInit2....");
    }
}

 

测试方法:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-schema.xml");
        AspectBiz aspectBiz = (AspectBiz)context.getBean("aspectBiz");
        //aspectBiz.save();
        aspectBiz.init("11",12);
    }
}

 

配置文件:

<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">
    <bean id="moocAspect" class="com.base.java.aop.schema.MoocAspect"></bean>
    <bean id="aspectBiz" class="com.base.java.aop.schema.AspectBiz"></bean>

    <aop:config>
        <aop:aspect id="moocAspectAOP" ref="moocAspect">
            <aop:pointcut expression="execution(* com.base.java.aop.schema.*Biz.*(..))" id="moocPiontcut"/>
            <aop:before method="before" pointcut-ref="moocPiontcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="moocPiontcut"/>
            <aop:after method="after" pointcut-ref="moocPiontcut"/>
            <aop:around method="around" pointcut-ref="moocPiontcut"/>
            <aop:around method="around" pointcut="execution(* com.base.java.aop.schema.AspectBiz.init(String,int))) and args(name, times)"/>
        </aop:aspect>
    </aop:config>
</beans>

 

④introduction引入增强的一个例子:

Fit

public interface Fit {
    void filter();
}

 

FitImpl

public class FitImpl implements Fit {
    @Override
    public void filter() {
        System.out.println("FitImpl filter");
    }
}

 

测试方法:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-schema.xml");
        //此处获取的是接口
        Fit fit = (Fit)context.getBean("aspectBiz");
        fit.filter();
    }
}

 

配置文件:

<bean id="moocAspect" class="com.base.java.aop.schema.MoocAspect"></bean>
    <bean id="aspectBiz" class="com.base.java.aop.schema.AspectBiz"></bean>

    <aop:config>
        <aop:aspect id="moocAspectAOP" ref="moocAspect">
            <aop:declare-parents types-matching="com.base.java.aop.schema.*" implement-interface="com.base.java.aop.schema.Fit" default-impl="com.base.java.aop.schema.FitImpl"/>
        </aop:aspect>
    </aop:config>
</beans>

 

说明:

引入增强是类级别的,所以不存在切点表达式。

利用 <aop:declare-parents> 节点在 <aop:aspect> 内部声明

types-matching 属性,要增强的目标类,这里需要全类名。

implement-interface 属性:动态的增强类接口。

default-impl 属性:动态增强类接口的实现类。

 

⑤Advisors

   Adivisor是一种特殊的Aspect,Advisor代表spring中的Aspect 
    advisor只持有一个Pointcut和一个advice,而aspect可以多个pointcut和多个advice

 

基于事务xml配置:

<tx:advice id="daoAdvice" transaction-manager="transactionManager">

     <tx:attributes>

            <tx:method name="delect*" propagation="REQUIRED"/>

            <tx:method name="*" propagation="REQUIRED" read-only="true"/>        

        </tx:attributes>

    </tx:advice>

<aop:config>

     <aop:pointcut expression="execution(* dao.*.*(..))" id="daoMethod"/>

     <aop:advisor advice-ref="daoAdvice" pointcut-ref="daoMethod"/>

</aop:config>

 

  • @ASpectJ注解驱动的AOP

@AspectJ是一种使用java注解来实现AOP,这种风格是在AspectJ5引入,并且spring也支持这种风格。

对@AspectJ支持可以使用XML或Java风格配置,不论哪种配置我们要引入aspectjweaver.jar,版本在1.6.8或者更高。

 

1)Java方式配置:

@Configuration

@EnableAspectJAutoProxy

public class AppConfig {

}

 

2)XML方式配置:

<aop:aspectj-autoproxy/>

 

3)切入点表达式:

AspectJ 指示器

描述

arg ()

限制连接点的指定参数为指定类型的执行方法

@args ()

限制连接点匹配参数由指定注解标注的执行方法

execution ()

用于匹配连接点的执行方法

this ()

限制连接点匹配 AOP 代理的 Bean 引用为指定类型的类

target ()

限制连接点匹配特定的执行对象,这些对象对应的类要具备指定类型注解

within()

限制连接点匹配指定类型

@within()

限制连接点匹配指定注释所标注的类型(当使用 Spring AOP 时,方法定义在由指定的注解所标注的类里)

@annotation

限制匹配带有指定注释的连接点

 

4)常用切入点表达式:

①匹配方法签名

// 匹配指定包中的所有的方法

execution(* com.xys.service.*(..))

// 匹配当前包中的指定类的所有方法

execution(* UserService.*(..))

// 匹配指定包中的所有 public 方法

execution(public * com.xys.service.*(..))

// 匹配指定包中的所有 public 方法, 并且返回值是 int 类型的方法

execution(public int com.xys.service.*(..))

// 匹配指定包中的所有 public 方法, 并且第一个参数是 String, 返回值是 int 类型的方法

execution(public int com.xys.service.*(String name, ..))

②匹配类型签名

// 匹配指定包中的所有的方法, 但不包括子包

within(com.xys.service.*)

// 匹配指定包中的所有的方法, 包括子包

within(com.xys.service..*)

// 匹配当前包中的指定类中的方法

within(UserService)

// 匹配一个接口的所有实现类中的实现的方法

within(UserDao+)

③匹配 Bean 名字

// 匹配以指定名字结尾的 Bean 中的所有方法

bean(*Service)

④切点表达式组合

// 匹配以 Service 或 ServiceImpl 结尾的 bean

bean(*Service || *ServiceImpl)

// 匹配名字以 Service 结尾, 并且在包 com.xys.service 中的 bean

bean(*Service) && within(com.xys.service.*)

⑤匹配参数

// 匹配第二个参数为 name 的方法

@Before(value = "aspectMethod()  &&  args(*, name, ..)")

public void doSomething(String name) {

}

5)@Aspect 

仅使用@AspectJ注解,是不能够通过类路径检测发现的,所以需要配合使用@component注解或者使用XML配置切面Bean。类使用@AspectJ之后,这个类就排除在auto-proxying机制之外。

6)@Pointcut

一个 pointcut 的声明由两部分组成:

一个方法签名, 包括方法名和相关参数,返回值类型为void。

一个 pointcut 表达式, 用来指定哪些方法执行是我们感兴趣的(即因此可以织入 advice)。

7)具体例子

配置文件:

<?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="com.base.java.aop.aspectj"/>
    <aop:aspectj-autoproxy />
</beans>

 

MoocBiz

@Service
public class MoocBiz {
    @MoocMethod("this is a annotation")
    public String save(String arg){
        System.out.println("MoocBiz save:" + arg);
        //throw new RuntimeException("save fail");
        return "Save success";
    }
}

 

MoocAscpet

@Component
@Aspect
public class MoocAscpet {
    @Pointcut("execution(* com.base.java.aop.aspectj.*Biz.*(..))")
    public void pointcut(){

    }

    @Pointcut("execution(* com.base.java.aop.aspectj.*Biz.*(..)) && @annotation(moocMethod)")
    public void pointcutAnnotation(MoocMethod moocMethod){

    }

    @Pointcut("within(com.base.java.aop.aspectj.*)")
    public void bizPointcut(){

    }
    @Before("pointcut()")
    //@Before("execution(* com.base.java.aop.aspectj.*Biz.*(..))")
    public void before(){
        System.out.println("Before......");
    }

    @Before("pointcut() && args(arg)")
    public void beforeWithParam(String arg){
        System.out.println("beforeWithParam : " + arg);
    }

    @Before("pointcut() && @annotation(moocMethod)")
    public void beforeWithAnnotation(MoocMethod moocMethod){
        System.out.println("beforeWithAnnotation " + moocMethod.value());
    }

    @Before("pointcutAnnotation(moocMethod)")
    public void beforeWithAnnotation1(MoocMethod moocMethod){
        System.out.println("beforeWithAnnotation1 " + moocMethod.value());
    }

    @AfterReturning(pointcut = "pointcut()",returning = "returnValue")
    public void afterReturning(Object returnValue){
        System.out.println("afterReturning : " + returnValue);
    }

    @AfterThrowing(pointcut = "pointcut()",throwing = "e")
    public void afterThrowing(RuntimeException e){
        System.out.println("afterThrowing : " + e.getMessage());
    }

    @After("pointcut()")
    public void after(){
        System.out.println("after.");
    }

    //方法第一个参数必须是ProceedingJoinPoint类型,返回值时Object
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("around1。。。");
        Object obj = point.proceed();
        System.out.println("around2...." + obj);
        return obj;
    }
}

 

MoocMethod

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MoocMethod {
    String value() default "";
}

 

测试类:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-aspectj.xml");
        MoocBiz biz = (MoocBiz) context.getBean("moocBiz");
        biz.save("this is test..");
    }
}

 

8)切面实例化模型

在@Aspect使用perthis后,每个独立的service对象执行时都会创建一个切面实例,切面实例在方法第一次调用时创建,在service对象失效时同时失效。使用方式:@Aspect("perthis(com.java.businessService())")。

9)AOP基于泛型的应用

Base

public interface Base<T> {
    public void save(T t);
    public void update(T t);
}

 

BaseImpl

public class BaseImpl<T> implements Base<T> {
    @Override
    public void save(T t) {
        System.out.println("BaseImpl-save()");
    }

    @Override
    public void update(T t) {
        System.out.println("BaseImpl-update()");
    }
}

 

BaseAspect

@Aspect
@Component
public class BaseAspect<T> {
    @Before("execution(* com.base.java.aop.aspectj.BaseImpl.save(..)) && args(t))")
    public void save(T t){
        System.out.println("aspect - save(), " + t.getClass().getSimpleName());
    }

    @Before("execution(* com.base.java.aop.aspectj.BaseImpl.update(..)) && args(t))")
    public void update(T t) {
        System.out.println("aspect - update(), " + t.getClass().getSimpleName());
    }
}

 

ObjectA

public class ObjectA {
}

 

ObjectAService

public interface ObjectAService extends Base<ObjectA> {
    public void supportMethod(ObjectA a);
}

 

ObjectAServiceImpl

@Service("obaService")
public class ObjectAServiceImpl extends BaseImpl<ObjectA> implements ObjectAService {
    @Override
    public void supportMethod(ObjectA a) {
        System.out.println("supportMethod");
    }

@Override
    public void save(ObjectA a){
        System.out.println("-------------------");
    }
}

 

测试类:

public class MainTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop-aspectj.xml");
        ObjectAService biz = (ObjectAService) context.getBean("obaService");
        biz.supportMethod(new ObjectA());
        biz.save(new ObjectA());
        biz.update(new ObjectA());
}
}

 

输出结果:

supportMethod

aspect - save(), ObjectA

-------------------

aspect - update(), ObjectA

BaseImpl-update()

 

注意:存在继承关系的类中,如果对父类做切面,其子类同时也会被切到。对类做切面使用的是CGLib代理,对接口对切面使用的是JDK代理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值