ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

注解开发Spring AOP

2022-01-25 22:30:00  阅读:150  来源: 互联网

标签:Spring aop ssm role AOP 注解 import com public


AOP的概念和理解:使用画图的方式理解面向切面编程(AOP)

AOP的术语以及XML配置方式快速入门

(1)创建目标接口以及实现类

package com.ssm.aop.service;

import com.ssm.aop.game.Role;

public interface RoleService {
    public void printRole(Role role);
}
package com.ssm.aop.service.Impl;

import com.ssm.aop.game.Role;
import com.ssm.aop.service.RoleService;
import org.springframework.stereotype.Component;

@Component
public class RoleServiceImpl implements RoleService {

    @Override
    public void printRole(Role role) {
        System.out.println("{id: "+role.getId()+", "
        +"role_name:"+role.getRoleName()+", "
        +"note:"+role.getNote()+"}");
    }
}

(2)创建切面类(用于增强目标类的方法)

package com.ssm.aop.aspect;

import org.aspectj.lang.annotation.*;

@Aspect
public class RoleAspect {
    @Before("execution(* com.ssm.aop.service.Impl.RoleServiceImpl.printRole(..))")
    public void before()
    {
        System.out.println("before...");
    }
    @After("execution(* com.ssm.aop.service.Impl.RoleServiceImpl.printRole(..))")
    public void after()
    {
        System.out.println("after...");
    }
    @AfterReturning("execution(* com.ssm.aop.service.Impl.RoleServiceImpl.printRole(..))")
    public void afterReturning()
    {
        System.out.println("afterReturning...");
    }
    @AfterThrowing("execution(* com.ssm.aop.service.Impl.RoleServiceImpl.printRole(..))")
    public void afterThrowing()
    {
        System.out.println("afterThrowing...");
    }

}

在类的上方加上@Aspect注解,就表明该类为切面类

@Before:添加该注解的方法表明该方法在被代理对象的方法前调用,即前置通知

@After:添加该注解的方法表明该方法在被代理对象的方法后调用,即后置通知

@AfterReturning:添加该注解的方法表明该方法在被代理对象的方法正常返回后调用。

@AfterThrowing:添加该注解的方法表明该方法在被代理对象的方法抛出异常后调用。

方法上的注解括号中的配置项(定义了execution的正则表达式,来匹配对应的切点)用于定义切点:

表达式的语法:

execution([修饰符]返回值类型 包名.类名.方法名(参数))

  • 访问的修饰符可以省略
  • 返回值类型、包名、类名、方法名可以使用*代表任意
  • 包名与类名之间一个点.代表当前包下的类,两个点..表示当前包及其子包下的类
  • 参数列表可以使用两个点..表示任意个数,任意类型的参数列表。

以下面的表达式为例:

execution(* com.ssm.aop.service.Impl.RoleServiceImpl.printRole(..))

execution:代表执行方法时会触发

*:代表任意返回类型的方法

com.ssm.aop.service.Impl.RoleServiceImpl:代表类的全限定名

printRole:被拦截的方法名称

(..):任意的参数

上述切面类中,切点的定义是重复的代码,比较麻烦,可以通过引入@Pointcut定义一个切点就可以避免该麻烦

在一个没有任何逻辑的方法上方定义@Pointcut注解,配置项为切点的表达式即可,在使用时只要在配置项配置没有逻辑的方法名即可。

改进后的代码如下

package com.ssm.aop.aspect;

import org.aspectj.lang.annotation.*;

@Aspect
public class RoleAspect {

    @Pointcut("execution(* com.ssm.aop.service.Impl.RoleServiceImpl.printRole(..))")
    public void print()
    {
        
    }
    @Before("print()")
    public void before()
    {
        System.out.println("before...");
    }
    @After("print()")
    public void after()
    {
        System.out.println("after...");
    }
    @AfterReturning("print()")
    public void afterReturning()
    {
        System.out.println("afterReturning...");
    }
    @AfterThrowing("print()")
    public void afterThrowing()
    {
        System.out.println("afterThrowing...");
    }

}

(3)配置

要使得上述的注解有效,要先启动AspectJ自动代理,这样Spring才会生成动态代理对象。

配置代码如下:

package com.ssm.aop.config;

import com.ssm.aop.aspect.RoleAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.ssm.aop")
public class AopConfig {
    @Bean
    public RoleAspect getRoleAspect()
    {
        return new RoleAspect();
    }
}

@EnableAspectJAutoProxy

 @Bean
    public RoleAspect getRoleAspect()
    {
        return new RoleAspect();
    }

该部分代码就代表了启动了AdpectJ框架的自动代理

另一种启用自动代理是通过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
">
    <aop:aspectj-autoproxy/>
    <bean id="roleAspect" class="com.ssm.aop.aspect.RoleAspect"/>
    <bean id="roleService" class="com.ssm.aop.service.Impl.RoleServiceImpl"/>

</beans>

可以看到XML中将RoleAspect切面类和RoleServiceImpl目标类作为bean加入Ioc容器,相当于注解中的@Bean和@Component

<aop:aspectj-autoproxy>跟注解@EnableAspectJautoProxy作用相同,启用自动代理功能。

(4)测试

测试代码如下:

import com.ssm.aop.config.AopConfig;
import com.ssm.aop.game.Role;
import com.ssm.aop.service.RoleService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AopConfig.class);//使用config类配置
       // ApplicationContext ctx=new ClassPathXmlApplicationContext("application-config.xml");//使用xml配置文件
        RoleService roleService = (RoleService) ctx.getBean(RoleService.class);
        Role role = new Role();
        role.setId(1L);
        role.setRoleName("role_name_1");
        role.setNote("note_1");
        roleService.printRole(role);
        System.out.println("####################");
        //测试异常通知
        role = null;
        roleService.printRole(role);
    }
}

运行结果如下图;

 在测试代码中特意创建了一个空对象来触发异常通知。

在没有错误的情况下,可以看到首先调用前置通知,然后调用printRole方法,再调用了成功返回的通知,最后调用后置通知。

在抛出异常的情况下,首先调用了前置通知,然后调用pringRole方法时出现异常,则调用异常通知输出afterThrowing,最后调用后置通知。

也就是说无论调用pringRole成功与否,都会调用后置通知。

标签:Spring,aop,ssm,role,AOP,注解,import,com,public
来源: https://blog.csdn.net/Monkeydesigner/article/details/122692278

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有