SpringAOP的三种实现方式(schemabased,aspectj,注解)

SpringAOP面向切面编程

AOP的作用:
在不修改原有代码的基础上完成功能的扩展
AOP的方式:
  1. Schema-based方式
  2. Aspecjt方式
  3. 注解方式
AOP的Schema-based方式实现
①导入jar包 AOP的jar和IOC的jar

链接:https://pan.baidu.com/s/17cxb5fPX83CVDAJ67IwPLg

提取码:jxv7

②配置applicationcontext.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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">

<!--配置学生的bean 注意生成的代理的对象要和学生类实现同一个接口-->
<bean id="stu" class="pojo.StudentImpl"></bean>

<!--配置前置通知bean,部件 实现MethodBeforeAdvice接口-->
<bean id="a" class="advice.Before"></bean>
<!--配置后置通知bean,部件 实现AfterReturningAdvice接口-->
<bean id="b" class="advice.After"></bean>

<!--配置环绕通知bean:部件,实现MethodInterceptor接口-->
<bean id="c" class="advice.MyRound"></bean>
<!--配置异常通知bean:部件,实现ThrowsAdvice接口-->
<bean id="d" class="advice.MyThrow"></bean>


<aop:config>
<!--声明切点,如果有返回值,在方法中只声明返回值的类型 例如show(String,int)-->
<aop:pointcut id="my" expression="execution(* pojo.StudentImpl.show())"></aop:pointcut>
<!--将切点和通知组装起来-->
<aop:advisor advice-ref="a" pointcut-ref="my"></aop:advisor>
<aop:advisor advice-ref="b" pointcut-ref="my"></aop:advisor>
<aop:advisor advice-ref="c" pointcut-ref="my"></aop:advisor>
<aop:advisor advice-ref="d" pointcut-ref="my"></aop:advisor>
</aop:config>

</beans>

③使用扩展对象完成功能开发。

​ Student接口,实际对象和代理对象都要实现这个接口

public interface Student {
    void show();
}

​ 后置通知类

import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
 * 后置通知类:
 *  声明:实现AfterReturningAdvice接口
 *  作用:在切点执行之后执行.
 *  使用:需要在applicationcontext.xml中配置为bean标签,同时引入到切面声明中
 *  方法:afterReturning
 *  参数:
 *          Object o:切点执行的返回值
 *          Method method:切点方法的方法对象
 *          Object[] objects:实参的数组
 *          Object o1:切点所隶属的对象,真实对象。
 */
public class After implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("我是后置通知");
    }
}

​ 前置通知类

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;
/**
 * 前置通知类:
 *  声明:实现MethodBeforeAdvice接口
 *  作用:在切点执行之前执行.
 *  使用:需要在applicationcontext.xml中配置为bean标签,同时引入到切面声明中
 *  方法:before
 *  参数:
 *          Method method:切点方法的方法对象
 *          Object[] objects:实参的数组
 *          Object o:切点所隶属的对象,真实对象。
 */
public class Before implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("我是前置通知");
        //        method.invoke(o,objects);
    }
}

​ 环绕通知类

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
 * 环绕通知类:
 *  声明:实现MethodInterceptor接口
 *  作用:环绕执行,拦截切点。需要放行.类似于拦截器
 *  使用:需要在applicationcontext.xml中配置为bean标签,同时引入到切面声明中
 *  方法:invoke
 *  参数:
 *         MethodInvocation methodInvocation
 */

public class MyRound implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("环绕前");
        Object proceed = methodInvocation.proceed();//放行,类似于拦截器
        System.out.println("环绕后");
        return proceed;
    }
}

​ 异常通知类

import org.springframework.aop.ThrowsAdvice;
/**
 * 异常通知类:
 *  声明:实现ThrowsAdvice接口
 *  作用:处理代理对象执行的异常信息,如果出现异常会执行这个通知类
 *  使用:需要在applicationcontext.xml中配置为bean标签,同时引入到切面声明中
 *  方法:afterThrowing
 *  参数:
 *          Exception ex:接收异常信息。
 */
public class MyThrow implements ThrowsAdvice {
    //方法必须时这个名
    public void afterThrowing(Exception ex) throws Throwable {
        System.out.println("我是异常通知");
    }

}
AOP的Aspecjt方式实现
①导入jar包 AOP的jar和IOC的jar

链接:https://pan.baidu.com/s/17cxb5fPX83CVDAJ67IwPLg

提取码:jxv7

②配置applicationcontext.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/aop
                           http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="stu" class="pojo.Student"></bean>

    <!--声明通知类-->
    <bean id="advice" class="advice.MyAdvice"></bean>
    <!--作用:可以声明多个,一个表示一组扩展,只对该组内切点有效-->
    <aop:config>
        <!--声明切点-->
        <!--
            配置切点:
                切点的表达式支持通配符(schema和ascpectj都支持)*
                   pojo.Student.stuDemo(..)
                        表示:参数任意类型任意个数的stuDemo方法
                   pojo.Student.*(..)
                        表示:student对象中的所有方法
                   pojo.*.*(..)
                        表示:pojo包下的所有类的所有方法
                一般会用在给业务层的方法进行统一增加扩展功能:
                    com.bjsxt.service.impl.*.*(..)
        -->
        <aop:pointcut id="my" expression="execution(* pojo.Student.show())"></aop:pointcut>
        <!--ref属性 和通知类关联-->
        <aop:aspect ref="advice">
            <!--前置通知-->
            <aop:before method="before" pointcut-ref="my"></aop:before>
            <aop:after method="after" pointcut-ref="my"></aop:after>
            <aop:around method="around" pointcut-ref="my"></aop:around>
            <!--
                配置异常通知方法:
                    需要在异常标签中使用throwing属性,属性值为异常通知方法的形参名,
                    来表明需要将异常信息传递给异常通知方法使用
            -->
            <aop:after-throwing method="Mythrow" pointcut-ref="my" throwing="e"></aop:after-throwing>

        </aop:aspect>
    </aop:config>

</beans>

接口的实现类

public class Student implements StudentInf {
    @Override
    public void show() {
        System.out.println("我是学生");
    }
}

通知类:

package advice;

import org.aspectj.lang.ProceedingJoinPoint;

public class MyAdvice {
    public void before(){
        System.out.println("我是前置通知");
    }

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

    public void around(ProceedingJoinPoint pp) throws Throwable {
        System.out.println("环绕前");
        pp.proceed();     //放行
        System.out.println("环绕后");
    }

    public void Mythrow(Exception e){
        System.out.println("我是异常通知");
    }
}

测试类

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.StudentInf;

public class Test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml");
        StudentInf stu = (StudentInf) ac.getBean("stu");
        stu.show();
    }
}
AOP的注解方式实现
注意:SpringAOP只有AspectJ方式可以使用注解方式完成相同配 置,SchemaBased不支持注解方式
SpringAOP的注解实现:
@Compent:

​ 作用:相当于配置了bean标签,默认类名首字母小写为 bean的ID

​ 使用:在类名上使用

@AspectJ:

​ 作用:声明该类对象为通知类对象。

​ 使用:声明在类名上,结合@Compent使用

@Pointcut:

​ 作用:声明切点

​ 使用:在切点方法上。

@Before:

​ 作用:声明前置通知方法

​ 使用:在前置通知方法上

@After:

​ 作用:声明后置通知方法

​ 使用:在后置通知方法上

@Around:

​ 作用:声明环绕通知方法

​ 使用:在环绕通知方法上

@Throwing:

​ 作用:声明异常通知方法

​ 使用:在异常通知方法上

配置配置文件applicationcontext.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"
       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.xsd
                           http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd
                           ">
    <!--配置注解扫描-->
    <context:component-scan base-package="advice,pojo"></context:component-scan>
    <!--配置aop注解生效-->
    <aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
</beans>

学生的实现类

import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
public class Student implements StudengInf {
    @Override
    //切点上配置方法的路径
    @Pointcut("execution(* pojo.Student.show())")
    public void show() {
        System.out.println("我是学生");
    }
}

通知类

package advice;

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

@Component
@Aspect
public class Myadvice {
    @Before("pojo.Student.show()")
    public void before(){
        System.out.println("我是前置通知");
    }
    @After("pojo.Student.show()")
    public void after(){
        System.out.println("我是后置通知");
    }

    @Around("pojo.Student.show()")
    public void round(ProceedingJoinPoint pp) throws Throwable {
        System.out.println("环绕前");
        pp.proceed();
        System.out.println("环绕后");
    }

    /*throwing = "e"写的时形参的名字*/
    @AfterThrowing(value = "pojo.Student.show()",throwing = "e")
    public void myThrow(Exception e){
        System.out.println("我是异常通知");
    }
}

测试类

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.StudengInf;

public class Test {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationcontext.xml");
        /*id默认类名小写*/
        StudengInf student = (StudengInf) ac.getBean("student");
        student.show();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值