第3章 AOP(3课时)

动态代理学习:https://www.cnblogs.com/daniels/p/8242592.html

第一节

AOP基础

Aspect Oriented Programming (面向切面编程)
作用:1)一次解决一类问题
2)在不修改原有代码的基础上来扩展程序(开闭原则)
第一种 针对有接口的类,是采用jdk动态代理(横向扩展 接口-实现类)
第二种 针对无接口的类,是采用cglib代理(纵向扩展 继承)


image.png

名词:

关键的

Joinpoint(连接点):一个类当中的方法,或者说一个类里的哪些方法是可以被扩展或增强的
Pointcut(切入点):(从哪下手) 类里面有很多方法都可以被扩展或增加,但是我这次要扩展或增加的哪个方法 (事先写好的)
Advice(通知/增强):扩展或增强的逻辑(比如我在add方法前加日志,那么这个日志功能就叫通知或增强) 新写了一个方法—写的(后写的)
Aspect(切面)(配置实现):把增强应用到切点的过程。也就是把新写的方法应用到原有方法的过程 --配置的 (配置的 满足哪些条件的类或方法)

***** 通知或增强的类别(时机) (配置的)
1)前置增强:有原有方法执行前执行 before
2)后通知(After (finally) advice)最终:当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)
3)环绕:在方法前和后都可以执行他可以把原方法包起来 他需要拿到原有方法 around advice
无论方法是否正常结束, after通知都会被执行
4)返回后增强:有原有方法执行后执行 after-returning
5)抛出异常后通知:有原有方法执行产生异常 after-throwing
4或5只能执行一个

执行顺序参考

https://blog.csdn.net/qq_32331073/article/details/80596084
同一个aspect,不同advice的执行顺序:
注意:spring的5.2.7版本以后,执行顺序有所调整,具体的顺序以你选择的spring版本测试结果为准

    try{
        try{
            //@Around
            //@Before
            method.invoke(..);
            //@Around
        }catch(){
            throw.....;
        }finally{
            //@After
        }
        //@AfterReturning
    }catch(){
        //@AfterThrowing
    }

①没有异常情况下的执行顺序:

@Around(before)-> @Before-> 目标方法-> @Around(after)-> @After-> @AfterReturning;

②有异常情况下的执行顺序:

@Around(before)-> @Before-> 目标方法->@Around(after)(如果没有写在finally块里就执行不到了)-> @After-> @AfterThrowing;

以下了解

Target:目标对象- 被增强方法所在的类
Waving:织入-把增强应用到目标的过程
Proxy:代理-一个类被aop织入增强后,就会在底层产生一个代理类
如果有接口的类-动态代理
没有接口的类-cglib代理

第2节 xml配置方式

工程spring study下
1)引jar包pom.xml里加入

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.1</version>
    </dependency>

2)原有的dao类

package com.neuedu.dao.impl;

import org.springframework.stereotype.Repository;

import com.neuedu.dao.IUserDao;
@Repository("userDao")
public class UserDaoImpl implements IUserDao {

    @Override
    public int login(String username, String password) {
        System.out.println("dao方法被调用");
        return 1;
    }

}

2)写一个用于增强的类

public class LogHandler{

private void logbegin(){//横切逻辑
    
    System.out.println("---------------记录时间------------------"+System.currentTimeMillis());
}
private Object transaction(ProceedingJoinPoint jp) throws Throwable {
    System.out.println("-------------事务开始-------------");
    Object result = jp.proceed();
    System.out.println("-------------事务结束-------------");
    return result;
}
    public void logError(){
   System.out.println("异常了");
    }
}

3)配置

修改头部定义

<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-4.3.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-4.3.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

写配置

 <!-- 定义增强类,我计划把他织入到指定方法里面去 (普通的bean)-->
<bean id="logHandler" class="com.neuedu.springstudy.LogHandler"></bean>
<!-- 开始配置aop -->
<aop:config>
    <!-- 定义一个切面,引用切面类-->
    <aop:aspect ref="logHandler">
        <!--定义通知和切入点-->
        <!--  execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?) -->
        <!--前置通知-->
        <aop:before method="logbegin" pointcut="execution (* login*(..))"/> 
        <!--环绕通知-->
        <aop:around method="transaction" pointcut="execution (* com.neuedu.dao.*.*(..))"/>
         <!--异常通知-->
        <aop:after-throwing method="logError" pointcut="execution(* com.neuedu.model.dao.impl.*.login*(..))"/>

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

常用的表达式

execution(访问修饰符 <返回值类型><方法名)(参数列表))
execution(* spring.aop.chap02.Book.add(..))   表示对spring.aop.chap02. Book类的add方法进行增强
execution(* spring.aop.chap02.Book.*(..))   表示对spring.aop.chap02. Book类的所有方法进行增强
execution(* *.*(..))   表示对所有类的所有方法进行增强(不常用)
下面是用以指定字符开头的方法
execution(* save*(..))
execution(* update*(..))
execution(* del*(..))

注解扫描方式

注意开启代理开关 <aop:aspectj-autoproxy />

    <?xml version="1.0" encoding="UTF-8"?>
    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
      <!-- 在这里,配置包扫描,扫描model层所在的包 (service+dao) -->
      <context:component-scan base-package="com.neuedu"></context:component-scan>
      <!-- aop自动代理,加上这行后,会扫描带有@Aspect的注解 -->
      <aop:aspectj-autoproxy />
    </beans>

类的写法同下

第3节

第3节 java类注解方式

工程名:spring-java
1)引jar包改pom
2)拷贝刚才写的增强类loghandler
注意加必要的注解

@Aspect//该注解表示这个类是一个切面
@Component
public class LogHandler{
@Before("execution(* login*(..))")
    private void logbegin(){//横切逻辑
        System.out.println("---------------记录时间------------------"+System.currentTimeMillis());
    }
    @Around("execution(* com.neuedu.module.dao.*.*(..))")
    private Object transaction(ProceedingJoinPoint jp) throws Throwable {
        
        long begin=System.currentTimeMillis();
        System.out.println("-------------事务开始-------------"+begin);
        Object result = jp.proceed();
        long end=System.currentTimeMillis();
        System.out.println("-------------事务结束-------------"+end);
        System.out.println("执行时间"+(end-begin));
        return result;
    }
}

3)修改ModuleConfig.java,AspectJ自动扫描支持

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages={"com.neuedu"})
public class ModuleConfig {
  
}

4)运行原有测试类。看效果

public class SpringJTest {
   @Test
   public void test1(){
      //加载配置文件 (AnnotationConfigApplicationContext注解配置文件方式)
       ApplicationContext ctx=new AnnotationConfigApplicationContext(ModuleConfig.class);
      //读取bean
       IUserService service=(IUserService) ctx.getBean("userService");
      //调用bean里的方法
       service.login("陈昊", "123456");
   }
}

目前学到的注解:

@Service @Repository @Component @Before @After @Around @Configuration @EnableAspectJAutoProxy @ComponentScan @Aspect @Bean @Autowired @Qulifired

作业:
1)看线上学习部分
2)做一套笔试题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • 一、Java平台上AOP实现机制 1、jdk动态代理:利用拦截器(拦截器必须实现InvocationHanlder...
    七离_82cd阅读 534评论 0 0
  • Spring的AOPAOP的基本概念基于注解的“零配置”方式定义切面Bean定义Before增强处理定义After...
    渐丶忘阅读 1,600评论 0 0
  • 1. AOP 概念:面向方面编程 实现AOP的语言为AOL Aspect-Oriented language 1....
    格林哈阅读 156评论 0 1
  • 本博中关于spring的文章:Spring IOC和AOP原理,Spring事务原理探究,Spring配置文件属性...
    Maggie编程去阅读 4,098评论 0 34
  • 概述 Spring是什么? Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但是现在已经不止于企...
    琅筑阅读 1,162评论 2 8