SpringAOP基于XML、注解快速上手

前言

AOP相关概念就不说了,复制粘贴没意思,本文主要是把概念转化为实际应用,让虚无的概念落地。

工程结构

在这里插入图片描述
首先,做一个基于Xml的,全程不使用注解(但是注解是真的方便)。
写一个简单的接口,用于后面的AOP进行切片。

接口IworkerAop

打工人接口,专门提供打工方法。

public interface IworkerAop {
    
    
    /**
     * 打工人要干活儿
     */
    void work();
    void work(String ...args);//用来测试参数获取
}

再整俩实现类

WorkerBoss,老板算不算打工人啊?

public class Boss implements IworkerAop {
    
    
    public void work() {
    
    
        System.out.println("boss sleep all day");
    }
    public void work(String... args) {
    
    
        for (int i = 0; i < args.length; i++) {
    
    
            String arg = args[i];
            System.out.println("arg:" + arg);
            args[i] = arg + "boss-work";
        }
    }
}
public class Worker implements  IworkerAop {
    
    
    public void work() {
    
    
        System.out.println("I'm coding");
    }
    public void work(String... args) {
    
    
        for (int i = 0; i < args.length; i++) {
    
    
            String arg = args[i];
            System.out.println( arg+" 开始工作");
            args[i] = arg + "hungry";
        }
    }
}

配置AOP方法

这些方法根据配置,会在切点执行。

public class AopXmlConfig {
    
    
	//之前执行
    public void beforeWork() {
    
    
        System.out.println("go to company");
    }
    //之后执行
    public void afterWork() {
    
    
        System.out.println("eat");
    }
}

做Xml的配置

application-aop.xml中配置之前写好的AOP方法,核心就在这里了,配切点,通知以及bean的注入。

<?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:contex="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">

    <!--让Spring帮我注入bean-->
    <bean name="aopXmlConfig" class="com.example.xml.aop.springaopxmldemo.aopConfig.AopXmlConfig"/>
    <bean name="boss" class="com.example.xml.aop.springaopxmldemo.workService.impl.Boss"/>
    <bean name="worker" class="com.example.xml.aop.springaopxmldemo.workService.impl.Worker"/>
    <!--配置AOP-->
    <aop:config>
        <!--配置切点-->
        <aop:pointcut id="workPointCut"
                      expression="execution(* com.example.xml.aop.springaopxmldemo.workService.IworkerAop.work(..))"/>
        <!--配置通知-->
        <aop:aspect ref="aopXmlConfig">
            <aop:before method="beforeWork" pointcut-ref="workPointCut"/>
            <aop:after method="afterWork" pointcut-ref="workPointCut"/>
        </aop:aspect>
    </aop:config>
</beans>

主类SpringAopXmlDemoApplication

主类获取bean实例,执行一下切入点的方法看看效果。

public class SpringAopXmlDemoApplication {
    
    
	public static void main(String[] args) {
    
    
		ApplicationContext context = new ClassPathXmlApplicationContext("application-aop.xml");
		IworkerAop worker = (IworkerAop) context.getBean("worker");
		worker.work();
	}

}

输出结果

可以看到,再AOP中配置的before和after方法成功切入。
在这里插入图片描述
老板说打工人只打工不行,加强一下,还得PUA打工人,不然老想着跳槽。
于是在打工人工作的时候进行PUA。

切入点方法参数获取以及修改

增加一个around通知方法:

public class AopXmlConfig {
    
    
    /**
     * 之前执行
     */
    public void beforeWork() {
    
    
        System.out.println("go to company");
    }
    /**
     * 环绕执行
     * @param point
     * @throws Throwable
     */
    public void aroundWork(ProceedingJoinPoint point) throws Throwable {
    
    
        Object[] values = point.getArgs();//使用数组获取参数
        printWorker(values);//打印参数
        point.proceed(new Object[]{
    
    new String[]{
    
    "通过老板PUA的打工人1", "通过老板PUA的打工人2"}});
        //注意这里,因为使用的是可变参数,实际上是数组,所以需要new数组作为参数,再放到一个数组里传入。

    }
    /**
     * 打印参数
     * @param values
     */
    private void printWorker(Object[] values) {
    
    
        for (Object o : values) {
    
    
            System.out.println("监控打工人数量:" + Arrays.toString(((String[]) o)));
        }
    }
    /**
     * 之后执行
     */
    public void afterWork() {
    
    
        System.out.println("eat");
    }
}

xml通知配置中增加一个环绕通知

 <aop:around method="aroundWork" pointcut-ref="workPointCut"/>

还记得打工人接口里面的一个可变参数列表方法吧,这个方法就是为了传入多个打工人的

public class SpringAopXmlDemoApplication {
    
    
	public static void main(String[] args) {
    
    
		ApplicationContext context = new ClassPathXmlApplicationContext("application-aop.xml");
		IworkerAop worker = (IworkerAop) context.getBean("worker");
		worker.work("打工人1","打工人2");
	}
}

执行结果

打工人被老板PUA,认真干活。
在这里插入图片描述

基于注解

基于注解就简单得多了,复制AopXmlConfig改造一下,在这里直接一步到位了哈,@Aspect配置切片,表示我这个类是配置AOP的,让Spring大哥你给我注意些,@Component自动注入bean,@Pointcut配置切点,@Before相关注解配置通知到相关方法上。另外,在工具人实现类上加上@Service注解,方便自动注入。

@Aspect
@Component
public class AopConfig {
    
    
    @Pointcut(value = "execution(* com.example.xml.aop.springaopxmldemo.workService.impl.*.work(..))")
    public void workPointCut() {
    
    
    }
    @Before(value = "workPointCut()")
    public void beforeWork() {
    
    
        System.out.println("anno-go to company");
    }
    @After(value = "workPointCut()")
    public void  afterWork() {
    
    
        System.out.println("anno-eat");
    }
}

主类配置

@EnableAspectJAutoProxy启用AOP,@ComponentScan扫描bean进行自动注入。

@EnableAspectJAutoProxy
@ComponentScan
public class SpringAopNoXmlDemoApplication {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringAopNoXmlDemoApplication.class);
        IworkerAop worker = (IworkerAop) context.getBean("worker");
        worker.work("打工人1","打工人2");
    }
}

执行结果

完全去掉了Xml,可怜的打工人又开始工作了

在这里插入图片描述

后记

在配置过程中有些值得注意的地方:

  • 在xml配置中可以启用注解进行混合配置,怎么方便怎么来;
  • 在获取bean实例的时候,我使用的是bean id的方式获取,这种方式默认使用小驼峰,也就是首字母小写的,需要注意;
  • 环绕方法参数获取以及处理的时候,这里使用可变参数,导致ProceedingJoinPointgetArgs()获取的数组结果里面还是数组;

总的来说SpringAOP只是概念原理复杂,但是使用上却意外的简单,特别是基于注解(懒人福音),掌握了注解配置,那么在SpringBoot中使用AOP方式是完全一样的。

猜你喜欢

转载自blog.csdn.net/Logicr/article/details/111112231