Java从入门到入土之Spring-AOP篇

AOP相关名词
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象):织入 Advice 的目标对象.。
schema-base方式增强
前置增强类

package com.demo;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

/*自定义类实现MethodBeforeAdvice接口*/
public class MyBefore implements MethodBeforeAdvice {
    /*实现before()方法,方法体为增强内容
    * 参数method 切点方法名
    * objects 参数集合
    * o 切点所在类的对象*/
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("前置通知,执行了");
    }
}

后置增强类

package com.demo;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

/*自定义类实现AfterReturningAdvice接口*/
public class MyAfter implements AfterReturningAdvice {

    /*实现afterReturning()方法,方法体为增强内容
     * o 返回值对象
     * 参数method 切点方法名
     * objects 参数集合
     * o1 切点所在类的对象*/
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("后置增强,执行了");
    }
}

异常增强

package com.demo;

import org.springframework.aop.ThrowsAdvice;

/*自定义类实现ThrowsAdvice接口*/
public class MyThrow implements ThrowsAdvice {

    /*异常通知spring不提供方法,需要自己写。并且名字固定
    * 参数 e 异常信息*/
    public void afterThrowing(Exception e) throws Throwable{
        System.out.println("异常通知,执行了");
    }
}

环绕增强

package com.demo;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/*自定义类实现MethodInterceptor接口*/
public class MyAround implements MethodInterceptor {

    /*实现invoke()方法*
    参数 methodInvocation 切点方法/
     */
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        /*前置增强先执行*/
        System.out.println("环绕前置通知,执行了");
        /*通过反射执行切点方法*/
        Object obj = methodInvocation.proceed();
        /*执行后置增强*/
        System.out.println("环绕后置通知,执行了");
        return obj;
    }
}

配置文件


<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-4.3.xsd">
        
        <bean id="demo" class="com.demo.Demo">bean>
        <bean id="myBefore" class="com.demo.MyBefore">bean>
        <bean id="myAfter" class="com.demo.MyAfter">bean>
        <bean id="myAround" class="com.demo.MyAround">bean>
        <bean id="myThrow" class="com.demo.MyThrow">bean>
        
        <aop:config>
            
            <aop:pointcut id="mypoint" expression="execution(* com.demo.Demo.a(..))"/>
            
            <aop:advisor advice-ref="myBefore" pointcut-ref="mypoint"/>
            
            <aop:advisor advice-ref="myAfter" pointcut-ref="mypoint"/>
            
            <aop:advisor advice-ref="myAround" pointcut-ref="mypoint"/>
            
            <aop:advisor advice-ref="myThrow" pointcut-ref="mypoint"/>
        aop:config>
beans>

切点类

package com.demo;

import org.springframework.stereotype.Component;

public class Demo {

    public String a(int a){
        System.out.println("Hello!");
        return "hello";
    }
}

测试类

package com.test;

import com.demo.Demo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Demo demo = (Demo) ac.getBean("demo");
        demo.a(1);
    }
}

运行结果

七月 25, 2019 2:43:50 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 14:43:50 CST 2019]; root of context hierarchy
七月 25, 2019 2:43:50 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
前置通知,执行了
环绕前置通知,执行了
Hello!
环绕后置通知,执行了
后置增强,执行了

Process finished with exit code 0

AspectJ方式增强
通知类

package com.demo;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/*不需要实现任何接口或继承类*/
public class MyAdvice {

        public void before(){
            System.out.println("前置增强,执行了");
        }
        /*发生异常不执行后置增强*/
        public void afterReturning(){
            System.out.println("后置增强,执行了");
        }
        /*无论是否发生异常都会执行after*/
        public void after(){
            System.out.println("最终增强,执行了");
        }
        public void afterThrow(){
            System.out.println("异常增强,执行了");
        }
        /*不发生异常,环绕前置,后置都执行
        * 发生异常只执行前置增强*/
        public void around(ProceedingJoinPoint joinPoint) throws Throwable{
            /*前置增强先执行*/
            System.out.println("环绕前置通知,执行了");
            /*通过反射执行切点方法*/
            Object obj = joinPoint.proceed();
            /*执行后置增强*/
            System.out.println("环绕后置通知,执行了");
        }

}

配置文件


<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-4.3.xsd">
        
        <bean id="demo" class="com.demo.Demo">bean>
        <bean id="myAdvice" class="com.demo.MyAdvice">bean>
    <aop:config>
        
        <aop:aspect ref="myAdvice">
            
            <aop:pointcut expression="execution(* com.demo.Demo.a(..))" id="mypoint"/>
            
            <aop:before method="before" pointcut-ref="mypoint"/>
            
            <aop:after-returning method="afterReturning" pointcut-ref="mypoint"/>
            
            <aop:after method="after" pointcut-ref="mypoint"/>
            
            <aop:after-throwing method="afterThrow" pointcut-ref="mypoint"/>
            
            <aop:around method="around" pointcut-ref="mypoint"/>
        aop:aspect>
    aop:config>
beans>

不出异常运行结果

七月 25, 2019 3:04:34 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 15:04:34 CST 2019]; root of context hierarchy
七月 25, 2019 3:04:34 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
前置增强,执行了
环绕前置通知,执行了
Hello!
环绕后置通知,执行了
最终增强,执行了
后置增强,执行了

出异常运行结果

七月 25, 2019 3:05:08 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 15:05:08 CST 2019]; root of context hierarchy
七月 25, 2019 3:05:08 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
前置增强,执行了
环绕前置通知,执行了
异常增强,执行了
最终增强,执行了

Process finished with exit code 0

使用注解方式
配置文件


<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"
       xmlns:context="http://www.springframework.org/schema/context"
       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-4.3.xsd
        http://www.springframework.org/schema/context
     	http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        
        <context:component-scan base-package="com.demo">context:component-scan>
        
        <aop:aspectj-autoproxy>aop:aspectj-autoproxy>
beans>

切点类

package com.demo;

import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
public class Demo {

    public String a(int a) throws Exception{
        /*制造异常,向上抛*/
        //int i = 1/0;
        System.out.println("Hello!");
        return "hello";
    }
}

增强(切面)类

package com.demo;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/*交给spring管理*/
@Component
/*指定该类为切面类*/
@Aspect
public class MyAdvice {

    /*定义切点*/
    @Pointcut("execution(* com.demo.Demo.a(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void before() {
        System.out.println("前置增强,执行了");
    }

    /*发生异常不执行后置增强*/
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("后置增强,执行了");
    }

    /*无论是否发生异常都会执行after*/
    @After("pointCut()")
    public void after() {
        System.out.println("最终增强,执行了");
    }

    @AfterThrowing("pointCut()")
    public void afterThrow() {
        System.out.println("异常增强,执行了");
    }

    /*不发生异常,环绕前置,后置都执行
     * 发生异常只执行前置增强*/
    @Around("pointCut()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        /*前置增强先执行*/
        System.out.println("环绕前置通知,执行了");
        /*通过反射执行切点方法*/
        Object obj = joinPoint.proceed();
        /*执行后置增强*/
        System.out.println("环绕后置通知,执行了");
    }

}

测试类

package com.test;

import com.demo.Demo;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Demo demo = (Demo) ac.getBean("demo");
        try {
            demo.a(1);
        } catch (Exception e) {
        }
    }
}

无异常运行结果

七月 25, 2019 3:16:14 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 15:16:14 CST 2019]; root of context hierarchy
七月 25, 2019 3:16:14 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
环绕前置通知,执行了
前置增强,执行了
Hello!
环绕后置通知,执行了
最终增强,执行了
后置增强,执行了

Process finished with exit code 0

有异常运行结果

七月 25, 2019 3:19:44 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31221be2: startup date [Thu Jul 25 15:19:44 CST 2019]; root of context hierarchy
七月 25, 2019 3:19:45 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
环绕前置通知,执行了
前置增强,执行了
最终增强,执行了
异常增强,执行了

Process finished with exit code 0

你可能感兴趣的:(Java从入门到入土之Spring-AOP篇)