Spring AOP 基础语法

Aop的相关术语、切点表达式、AOP的通知类型以及Spring整合Mybatis的案例笔记。

一、AOP相关术语

1.目标类Target:需要被增强的类、代理的目标对象。

2.连接点Joinpoint:目标类  可能  被增强的每一个方法。

3.切入点Pointcut:特殊的链接点,已经被增强了。

4.通知/增强Advice:增强的方法,需要添加的那段增强功能的逻辑代码。

5.切面Aspect:切入点和通知的结合

6.织入:增强添加到目标类的具体连接点上的过程。

7.代理Proxy:一个类被AOP织入增强后,就产生一个结果代理类。

二、切入点表达式 

1.作用:

通知/增强作用于具体切入点

2.基本格式:

指示符(表达式)

指示符分类:
execution:用于匹配方法执行的连接点;【重点】
within:用于匹配指定类型内的方法执行;
this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;
target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;
args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;
@within:用于匹配所以持有指定注解类型内的方法;
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;
@args:用于匹配当前执行的方法传入的参数持有指定注解的执行;
@annotation:用于匹配当前执行方法持有指定注解的方法;

3.execution 表达式

execution([修饰符] 返回值类型 包名.类名.方法名(参数类型列表) [throws 异常])
    返回值:
        void                   没有返回值
        int                    返回整数
        *                     表示返回任意值
    包名:
        com.czxy.user.dao    具体包名
        com.czxy.*.dao        任意模块的dao
        com.czxy.*sys.dao    固定后缀的包
        com.czxy.user.dao..    任意子包 (dao.impl包)
        com.czxy.*.dao..    任意模块,dao下任意子包 (dao.impl包)
    类名
        UserDao                具体类名
        *Dao                固定后缀
        User*                固定前缀
        *                    任意
    方法:
        findAll                具体方法名
        find*                固定前缀
        *All                固定后缀
        *                    任意
    (参数类型列表):
        ()                    无参
        (int)                第一个整形参数
        (int,int)            两个参数都是整形
        (*)                    任意一个参数
        (..)                参数任意
        
#综合
execution(* com.czxy..*.*(..))

三、通知类型

spring通知共5个分类:前置通知、后置通知、环绕通知、抛出异常通知、最终通知

1.位置:

try{
    // 前置通知、环绕通知
    // 目标类的方法
    // 后置通知、环绕通知
} catch() {
    // 抛出异常通知
} finally {
    // 最终通知
}

2.注解:

通知名称注解应用场景
前置通知@Before初始化、加载配置文件
后置通知@AfterReturning处理数据(Java对象转换成JSON字符串)
环绕通知@Around事务管理(开启事务、提交/回滚事务)
抛出异常通知@AfterThrowing错误日志管理
最终通知@After释放资源

3.测试:

3.1 前置通知:

切面类:

 /**
     * 前置通知
     * 参数1:JoinPoint joinPoint,可选
     */
    //@Before("execution(* com.czxy.demo16_aop_interface.service..*.*())")
    public void MyBefore(){//开启事务
        System.out.println("--------");
        System.out.println("前置通知");
    }

service实现类:

@Service
public class UserServiceImpl implements UserService {
    @Override
    public String insert() {
        System.out.println("添加");
        return "嗯嗯";
    }

    @Override
    public int update() {
        System.out.println("更新");
        return 250;
    }
}

测试类:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Demo16Configuration.class)
public class TestDemo16 {
    @Resource
    private UserService userService;

    @Test
    public  void run (){
        userService.insert();
        userService.update();
    }
}

测试结果:

 3.2后置通知:

切面类:

/**
     * 后置通知
     * 参数1:JoinPoint joinPoint,可选
     * 参数2:Object obj,可选
     *  要求1:类型必须Object
     *  要求2:变量名,必须与returning = "返回值变量名"一致
     */
    @AfterReturning(value = "execution(* com.czxy.demo16_aop_interface.service..*.*())" , returning = "obj")
    public void myAfterReturning(JoinPoint joinPoint , Object obj){//结束事务
        //通过JoinPoint可以获得连接点信息
        // 1 通过连接点获得方法签名,并获得方法名
        System.out.println(joinPoint.getSignature().getName());
        System.out.println("后置通知:"+obj);
    }

测试结果:

 3.3环绕通知:

切面类:

/**
     * 环绕通知
     *  要求1:返回值类型 Object
     *  要求2:参数类型 ProceedingJoinPoint ,【必须】 表示可运行的连接点
     *  要求3:需要手动执行目标方法,并处理异常
     *  要求4:执行目标方法后,需获得返回值,并返回
     * @return
     */
    @Around("execution(* com.czxy.demo16_aop_interface.service..*.*())")
    public Object myAround(ProceedingJoinPoint projoinPoint) throws Throwable {

        System.out.println("环绕前");

        // 手动执行目标方法,获得返回值
        Object obj = projoinPoint.proceed();
        System.out.println(obj);

        System.out.println("环绕后");

        // 返回
        return obj;
    }

测试结果:

 3.4抛出异常通知:

切面类:

/**
     * 抛出异常通知
     * 参数1:JoinPoint joinPoint,可选
     * 参数2:Exception e,可选
     *     要求1:类型必须Exception  ,表示异常
     *     要求2:变量名,必须与throwing = "返回值变量名"一致
     * @param joinPoint
     * @param e
     */
    //简单使用
    /*
    @AfterThrowing("execution(* com.czxy.demo16_aop_interface.service..*.*())")
    public void myAfterThrowing(){
        System.out.println("抛出异常通知");

    }
    */
    @AfterThrowing(value = "execution(* com.czxy.demo16_aop_interface.service..*.*())" , throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint , Exception e){
        //切入点的方法名
        System.out.println(joinPoint.getSignature().getName());
        System.out.println("抛出异常通知: " + e.getMessage());

    }

service实现类:

@Service
public class UserServiceImpl implements UserService {
    @Override
    public String insert() {
        System.out.println("添加");
        //模拟异常
        int i = 1/0;
        return "嗯嗯";
    }

    @Override
    public int update() {
        System.out.println("更新");
        return 250;
    }
}

测试结果:

 3.5最终通知:

切面类:

/**
     * 最终通知
     * 参数1:JoinPoint joinPoint,可选
     */
    @After("execution(* com.czxy.demo16_aop_interface.service..*.*())")
    public  void myAfter(){
        System.out.println("最终通知");
    }

测试结果:

 3.6抽取接入点表达式:

语法:

//声明切入点,建议私有方法
@Pointcut("抽取的切入点")
private void 方法名(){
}

//使用
@Before("方法名()") 	//方法名进行引用。

切面类:

@Component
@Aspect //支持AOP
public class MyAspect2 {

    /**
     * 抽取切入点表达式
     *
     * 建议方法私有
     */
    @Pointcut("execution(* com.czxy.demo16_aop_interface.service..*.*())")
    private void myPointCut(){}


    @Before("myPointCut()")
    public void myBefore(){//开启事务
        System.out.println("--------");
        System.out.println("前置通知");
    }



    //@AfterReturning(value = "myPointCut()" , returning = "obj")
    public void myAfterReturning(JoinPoint joinPoint , Object obj){//结束事务
        //通过JoinPoint可以获得连接点信息
        // 1 通过连接点获得方法签名,并获得方法名
        System.out.println(joinPoint.getSignature().getName());
        System.out.println("后置通知:"+obj);
    }



    //@Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint projoinPoint) throws Throwable {

        System.out.println("环绕前");

        // 手动执行目标方法,获得返回值
        Object obj = projoinPoint.proceed();
        System.out.println(obj);

        System.out.println("环绕后");

        // 返回
        return obj;
    }




    //@AfterThrowing(value = "myPointCut()" , throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint , Exception e){
        //切入点的方法名
        System.out.println(joinPoint.getSignature().getName());
        System.out.println("抛出异常通知: " + e.getMessage());

    }


    //@After("myPointCut()")
    public  void myAfter(){
        System.out.println("最终通知");
    }
}

四、Spring整合Mybatis案例

1.项目结构:

2.分析:

  • 步骤:

    • 编写UserMapper 接口,继承通用mapper

    • 编写UserService接口,查询所有、根据id查询详情、添加、修改、删除

    • 编写UserServiceImpl实现类,查询所有根据id查询详情、添加、修改、删除

    • 编写Spring配置类

    • 编写MyBatis配置类,取代 SqlConfigMap.xml文件

    • 测试类

3.实现:

环境:User + sql

public class User {
    @Id
    private String uid;
    private String username;
    private String password;
    private String name;
    private String email;
    private String telephone;
    private Date birthday;
    private String sex;
    private Integer state;
    private String code;

    @Override
    public String toString() {
        return "User{" +
                "uid='" + uid + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", telephone='" + telephone + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", state=" + state +
                ", code='" + code + '\'' +
                '}';
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public User(String uid, String username, String password, String name, String email, String telephone, Date birthday, String sex, Integer state, String code) {
        this.uid = uid;
        this.username = username;
        this.password = password;
        this.name = name;
        this.email = email;
        this.telephone = telephone;
        this.birthday = birthday;
        this.sex = sex;
        this.state = state;
        this.code = code;
    }

    public User() {
    }
}

 UserMapper:

public interface UserMapper extends Mapper<User> {
}

 service接口:

public interface UserService{

    /**
     * 查询所有
     * @return
     */
    List<User> selectAll();

    /**
     * 添加
     * @param user
     * @return
     */
    Integer insert(User user);

    /**
     * 根据id查询所有
     * @param uid
     * @return
     */
    User selectById(String uid);

    /**
     * 根据id删除
     * @param uid
     * @return
     */
    Integer delete(String uid);

    /**
     * 修改  更新
     * @param user
     * @return
     */
    Integer update(User user);
}

UserService实现类:

@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;


    @Override
    public List<User> selectAll() {
        return userMapper.selectAll();
    }

    @Override
    public Integer insert(User user) {
        return userMapper.insert(user);
    }

    @Override
    public User selectById(String uid) {
        return userMapper.selectByPrimaryKey(uid);
    }

    @Override
    public Integer delete(String uid) {
        return userMapper.deleteByPrimaryKey(uid);
    }

    @Override
    public Integer update(User user) {
        return userMapper.updateByPrimaryKey(user);
    }
}

Mybatis 配置类:

@Configuration
public class MybatisConfiguration {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        //1 创建工厂
        // 1.通过工厂bean创建对象,最后需要调用 getObject()获得具体的对象
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();

        //2 设置数据-- SqlMapConfig.xml 配置信息

        // 1.1 设置数据源
        factoryBean.setDataSource(dataSource);
        // 1.2 设置别名包扫描
        factoryBean.setTypeAliasesPackage("com.czxy.sm.domain");
        // 1.3 全局配置:驼峰映射
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setMapUnderscoreToCamelCase(true);
        factoryBean.setConfiguration(config);

        // 2 插件配置
        // 2.1 分页插件
        PageHelper pageHelper = new PageHelper();
        Properties pageProps = new Properties();
        pageProps.setProperty("dialect", "mysql");
        pageProps.setProperty("rowBoundsWithCount", "true");
        pageHelper.setProperties(pageProps);
        factoryBean.setPlugins(new Interceptor[] { pageHelper });


        // 返回SqlSessionFactory
        return factoryBean.getObject();
    }

    /**
     * 扫描Dao的包,查找各种XxxMapper接口,创建好UserMapper等对象存入到IOC的容器中
     * @return
     */
    @Bean
    public MapperScannerConfigurer mapperScanner() {
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.czxy.sm.mapper");
        return configurer;
    }
}

Spring配置类:

@Configuration
@PropertySource("classpath:db.properties")
@ComponentScan(basePackages = {"com.czxy.sm"})
public class SpringConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 连接池配置
     * @return
     */
    @Bean
    public DataSource dataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driver);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);

        return druidDataSource;
    }
}

db.properties文件:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_20211028
jdbc.username=root
jdbc.password=1234

测试类:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class, MybatisConfiguration.class})
public class TestSM {

    @Resource
    private UserService userService;

    @Test
    public void testSelectAll() {
        List<User> list = userService.selectAll();
        list.forEach(System.out::println);
    }

    @Test
    public void testInsert() {
        User user = new User();
        user.setUid("u009");
        user.setUsername("jack");
        user.setPassword("1234");

        System.out.println(userService.insert(user));
    }

    @Test
    public void testSelectById(){
        System.out.println(userService.selectById("u009"));
    }

    @Test
    public void testDelete(){
        System.out.println(userService.delete("u009"));
    }

    @Test
    public void testUpdate(){
        User user = new User();
        user.setUid("u009");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克2");

        System.out.println(userService.update(user));

    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值