spring AOC使用(面向切面)

通过实现接口并重写通知的方式

TargetInteface(如果是用jdk动态代理的方式,还是需要定义和实现接口)

public interface TargetInteface {
    void method1();
    void method2();
    int method3(Integer i);
}

目标类

public class Target implements TargetInteface{

    /*
    * 需要增强的方法,连接点JoinPoint
    **/
    public void method1() {
        System.out.println("method1 running ...");
    }

    public void method2() {
        System.out.println("method2 running ...");
    }

    public int method3(Integer i) {
        System.out.println("method3 running ...");
        return i;
    }
}

切面类,通过实现接口并重写方法的方式配置各种通知

public class TargetAdvice implements MethodInterceptor, MethodBeforeAdvice, AfterReturningAdvice {

    /*
    * 通知/增强
    **/
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("前置环绕通知");
        Object proceed = methodInvocation.proceed();
        System.out.println("后置环绕通知");
        return proceed;
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("后置返回通知");
    }

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置通知");
    }
}

测试类

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-aop.xml");//扫描xml文件
        Target targetProxy = (Target) appCtx.getBean("targetProxy");//从容器中获取代理对象
        targetProxy.method1();//执行方法,触发通知
    }
}

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"
       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">

    <bean id="target" class="com.heaboy.aopdemo.aop.Target"/>

    <bean id="targetAdvice" class="com.heaboy.aopdemo.aop.TargetAdvice"/>

    <bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="target"/> <!--被代理的类-->
        <property name="interceptorNames" value="targetAdvice"/>  <!--如果用多种增强方式,value的值使用逗号(,)分割-->
        <property name="proxyTargetClass" value="true"/>
        <property name="interfaces" value="com.heaboy.aopdemo.aop.TargetInteface"/>  <!--target实现的接口-->
    </bean>
</beans>

执行结果,可以看到执行了所有定义在TargetAdvice中的通知在这里插入图片描述

分割线————————————————————————————————————————————
通过配置xml的方式

/*
* 目标类
**/
public class Target {

    public void method1() {
        System.out.println("method1 running ...");
    }

    public void method2() {
        System.out.println("method2 running ...");
    }

    /*
    * 连接点JoinPoint
    **/
    public int method3(Integer i) {
        System.out.println("method3 running ...");
        int i1 = 1 / i;
        return i;
    }
}

此切面类定义了一些增强的通知,但是如果没有在xml中配置使用,他们就只是普通方法

/*
* 切面类
**/
public class TargetAspect {

    /*
    * 前置通知
    **/
    public void before() {
        System.out.println("conf前置通知");
    }

    public void after() {
        System.out.println("conf后置通知");
    }

    public void afterReturning() {
        System.out.println("conf后置返回通知");
    }

    public void afterThrowing(Exception ex) throws Exception {
        System.out.println("conf异常通知");
        System.out.println(ex.getMessage());
    }

    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed = null;
            System.out.println("conf环绕前置");
            proceed = pjp.proceed(pjp.getArgs());
            System.out.println("conf环绕后置");

        return proceed;
    }
}

测试类

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-confaop.xml");//扫描配置文件
        Target targetProxy = (Target) appCtx.getBean("target");//获取代理对象
        System.out.println(targetProxy.method3(0));//执行方法
    }
}

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 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">

    <bean id="target" class="com.heaboy.aopdemo.confaop.Target"/><!--注入target-->

    <bean id="targetAspect" class="com.heaboy.aopdemo.confaop.TargetAspect"/><!--注入切面类-->

    <!--proxy-target-class="true" 表示使用cglib代理.默认为false,创建有接口的jdk代理-->
    <aop:config proxy-target-class="true">
        <!--切面:由切入点和通知组成-->
        <aop:aspect ref="targetAspect">
            <!--切入点 pointcut-->
            <aop:pointcut id="pointcut" expression="execution(* com.heaboy.aopdemo.confaop.*.*(..))"/><!--代表执行此路径下的任何方法-->
            <!--增强/通知 advice-->
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after method="after" pointcut-ref="pointcut"/>
            <aop:around method="around" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut"/>
            <aop:after-throwing method="afterThrowing" throwing="ex" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>


</beans>

测试结果,可以看到配置的通知都执行了,配置的切面里面包含哪些通知就执行哪些通知(afterreturning没有执行,因为出现了异常,方法没有正常返回,但是后置通知正常执行)在这里插入图片描述

分割线————————————————————————————————————————————
通过注解的方式
自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation{
}

表示该注解用于方法上

<?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">

    <!--先开启cglib代理,开启 exposeProxy = true,暴露代理对象-->
    <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
    <!--扫包-->
    <context:component-scan base-package="com.heaboy.aopdemo.annotationaop"/>

</beans>

使用注解定义切面类(切点+通知)


/*
* 切面类
**/
@Aspect
@Component
public class AnnotationAspect {

    // 定义一个切点:所有被RequestMapping注解修饰的方法会织入advice
    @Pointcut("@annotation(TestAnnotation)")
    private void advicePointcut() {}

    /*
    * 前置通知
    **/
    @Before("execution(* com.heaboy.controller.*.*(..))")
    public void before() {
        System.out.println("annotation前置通知");
    }

    @After("advicePointcut()")
    public void after() {
        System.out.println("annotation后置通知");
    }

    @AfterReturning(pointcut = "advicePointcut()")
    public void afterReturning() {
        System.out.println("annotation后置返回通知");
    }

    @AfterThrowing(pointcut = "advicePointcut()", throwing = "ex")
    public void afterThrowing(Exception ex) throws Exception {
        System.out.println("annotation异常通知");
        System.out.println(ex.getMessage());
    }

    @Around("advicePointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object proceed = null;
        if (!"".equals("admin")) {
            System.out.println("annotation环绕前置");
            proceed = pjp.proceed(pjp.getArgs());
            System.out.println("annotation环绕后置");
        }
        return proceed;
    }
}

测试类(TestController)

@Controller
public class TestController {

    @RequestMapping("/test.do")
    @ResponseBody
    public String testController() {
        TestController o = (TestController) AopContext.currentProxy();
        o.test();
        return "ok";
    }

    @TestAnnotation
    public void test() {
        System.out.println("test running");
    }

}

通过controller执行test方法,方法执行时发现有 @TestAnnotation注解,将执行配置好的通知

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值