Loading

Spring学习-AOP

Spring学习-AOP

AOP

注意:需要在pom.xml中导入包:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

方式一:基于XML文件实现AOP(不定义切面)

XML文件

<?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:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
         
        <!--托管bean-->
        <bean id="target" class="com.example.demo.aop.TargetDemo"/>
        <bean id="log" class="com.example.demo.aop.Log"/>
        <bean id="security" class="com.example.demo.aop.Security"/>
            
        <!--定义AOP-->
        <aop:config> <!--AOP配置-->
            <!--定义切点,表示被切入的对象和方法-->
            <aop:pointcut id="pointcut" expression="execution(* com.example.demo.aop.TargetDemo.*(..))"/> 
            <!--在切点上定义一个前置通知-->
            <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
            <!--在切点上定义一个后置通知-->
            <aop:advisor advice-ref="security" pointcut-ref="pointcut"/>
        </aop:config>
</beans>

Java类:

// 切点类:表示该类方法被调用时,会先、后调用前置、后置通知
public class TargetDemo implements ITarget{

    public void doMyThings()
    {
        System.out.println("target object is running");
    }

}

// 通知类:方法执行前通知
public class Log implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("日志应该先被执行");
    }
}

// 通知类:方法返回后进行通知
public class Security implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("安全应该在目标对象后执行");
    }
}

// 测试类
public class MyTest {
    @Test
    public void test()
    {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
        ITarget bean = context.getBean("target", ITarget.class);
        bean.doMyThings(); // 方法被调用时,会先后调用对应的通知方法
    }
}

方式二(自定义切面)

切面:一个类,设置一些前置通知,后置通知等方法,切入到切点中。

XML文件:

<!--切面类,其中的方法可以切入到切点中-->
<bean id="aop" class="com.example.demo.test.AOP"/>

<aop:config>
    <aop:aspect ref="aop"><!--定义一个切面,为一个类,其中的方法可以切入到切点中-->
        <!--定义切点,在执行方法时,会被切面中定义的方法所切入-->
        <aop:pointcut id="pointcut" expression="execution(* com.example.demo.test.TargetDemo.*(..))"/>
        <!--定义一个前置通知,执行的方法是切面中的beforeMethod()方法-->
        <aop:before pointcut-ref="pointcut" method="beforeMethod"/>
         <!--定义一个后置通知,执行的方法是切面中的afterMethod()方法-->
        <aop:after pointcut-ref="pointcut" method="afterMethod"/>
    </aop:aspect>
</aop:config>

Java类:

// 切面类
public class AOP{
      public void beforeMethod(){
            System.out.println("前置通知被执行");
      }

      public void afterMethod(){
            System.out.println("后置通知被执行");
      }
}

方式三(基于注解)

// 切面类,定义前置,后置,环绕通过方法
@Aspect
public class AOP {

    @Before("execution(* TargetDemo.doMyThings(..))")
    public void before()
    {
        System.out.println("应该在之前被执行");
    }

    @After("execution(* TargetDemo.doMyThings(..))")
    public void after()
    {
        System.out.println("应该在之后被执行");
    }

    @Around("execution(* TargetDemo.doMyThings(..))")
    public void round(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前通知");
        jp.proceed();
        System.out.println("环绕后执行");
    }
}

XML文件:开启自动aop代理

<aop:aspectj-autoproxy/>
posted @ 2020-08-06 21:29  战五渣渣渣渣渣  阅读(66)  评论(0编辑  收藏  举报