Spring框架学习:Spring的AOP操作(十六)

准备工作:

1、Spring框架一般都是基于AspectJ实现AOP操作

(1)AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spirng框架一起使用,进行AOP操作

2、基于AspectJ实现AOP操作

(1)基于xml配置文件实现
(2)基于注解方式实现(使用)

3、在项目工程里面引入AOP相关依赖


spring基本jar包:
spring-aop-5.2.6.RELEASE.jar
spring-beans-5.2.6.RELEASE.jar
spring-context-5.2.6.RELEASE.jar
spring-core-5.2.6.RELEASE.jar
spring-expression-5.2.6.RELEASE.jar

aop部分jar包:
spring-aspects-5.2.6.RELEASE.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

其他:
commons-logging-1.1.1.jar
druid-1.1.9.jar

4、切入点表达式

(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构:execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
举例1:对com.atguigu.dao.BookDao类里面的add进行增强
execution(* com.atguigu.dao.BookDao.add(..))
举例2:对com.atguigu.dao.BookDao类里面的所有的方法进行增强
execution(* com.atguigu.dao.BookDao.*(..))
举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.*.*(..))

代码演示五种通知

User:

@Component
public class User {

    public void add(){
//        int i = 1/0;
        System.out.println("add 业务逻辑执行.....");
    }

}

增强代理类:

//增强的类
@Aspect //生成代理对象
@Component
public class UserProxy {

    //前置通知
    @Before("execution(* com.spring5.aopanno.User.add(..))")//前置通知
    public void before(){
        System.out.println("before-前置通知-......");
    }

    //后置通知(返回通知)-方法执行后-返回结果之后执行
    @AfterReturning("execution(* com.spring5.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning-后置通知(返回通知)-......");
    }

    //最终通知-方法执行之后执行
    @After("execution(* com.spring5.aopanno.User.add(..))")
    public void after(){
        System.out.println("after-最终通知......");
    }

    //异常通知
    @AfterThrowing("execution(* com.spring5.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing-异常通知......");
    }

    //环绕通知
    @Around("execution(* com.spring5.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("around-环绕之前通知-......");
        joinPoint.proceed();
        System.out.println("around-环绕之后通知-......");
    }

}

xml配置:
引入 context和aop名称空间

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

    <!--开启注解扫描-->
    <context:component-scan base-package="com.spring5.aopanno"></context:component-scan>

    <!--启用aspectj-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

junit测试类:

 @Test
    public void testAop(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();
    }

正常流程结果:

around-环绕之前通知-......
before-前置通知-......
add 业务逻辑执行.....
around-环绕之后通知-......
after-最终通知......
afterReturning-后置通知(返回通知)-......

业务逻辑异常时结果:

around-环绕之前通知-......
before-前置通知-......
after-最终通知......
afterThrowing-异常通知......

相同的切入点抽取

方便相同表达式修改

//相同切入点抽取
    @Pointcut("execution(* com.spring5.aopanno.User.add(..))")
    public void pointTest(){

    }
    //前置通知
    @Before("pointTest()")//前置通知
    public void before(){
        System.out.println("before-前置通知-......");
    }

多个增强类,作用于同一方法,设置优先级

数字越小,优先级越高

@Aspect
@Component
@Order(1)
public class PersonProxy {

    @Before("execution(* com.spring5.aopanno.User.add(..))")
    public void before(){
        System.out.println("person before .....");
    }
}

效果:

person before .....
around-环绕之前通知-......
before-前置通知-......
add 业务逻辑执行.....
around-环绕之后通知-......
after-最终通知......
afterReturning-后置通知(返回通知)-......

完成注解开发,使用配置类

@Configuration
@ComponentScan(basePackages = {"com.spring5.aopanno"})
@EnableAspectJAutoProxy
public class SpringConfig {
}

junit测试:

@Test
    public void testAopAnno(){
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        User user = context.getBean("user", User.class);
        user.add();
    }

XML方式实现通知

public class Book {

    public void buy(){
//        int i = 1/0;
        System.out.println("buy .....");
    }
}
public class BookProxy {

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

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

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

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

    public void around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("around-环绕之前通知-......");
        joinPoint.proceed();
        System.out.println("around-环绕之后通知-......");
    }
}
<?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="book" class="com.spring5.aopxml.Book"></bean>
    <bean id="bookProxy" class="com.spring5.aopxml.BookProxy"></bean>

    <!--配置aop增强-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="p" expression="execution(* com.spring5.aopxml.Book.buy(..))"/>
        <!--配置切面-->
        <aop:aspect ref="bookProxy">
            <!--增强作用在具体的方法上-->
            <aop:before method="before" pointcut-ref="p"></aop:before>
            <aop:after-returning method="afterReturning" pointcut-ref="p"></aop:after-returning>
            <aop:after method="after" pointcut-ref="p"></aop:after>
            <aop:after-throwing method="afterThrowing" pointcut-ref="p"></aop:after-throwing>
            <aop:around method="around" pointcut-ref="p"></aop:around>
        </aop:aspect>
    </aop:config>

</beans>
暂无评论

发送评论 编辑评论


				
上一篇
下一篇