文章目录

  • 1、AOP介绍
  • 2、 入门案例
    • 2.1、需求:
    • 2.2、实现思路:
  • 3、AOP作用和优势
  • 4、 入门案例2
    • 4.1、需求
  • 5、AOP实现方法
  • 6、相关AOP术语
  • 7、相关注解
    • 7.1、切入点表达式
    • 7.2、通知方法
    • 7.3、抽取公共切入点
  • 8、完整通知演示
    • 8.1、AOP编程
    • 8.2、目标接口和类
    • 8.3、配置类
    • 8.4、切面类
    • 8.5、测试类

1、AOP介绍

AOP:全称是Aspect Oriented Programming即:面向切面编程。
面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用代理的技术,在不修改原来代码的基础上,对已有方法进行增强。

2、 入门案例

2.1、需求:

User类中有方法eat . 现在在不修改eat方法的前提下,对eat进行增强. 增强的内容是,在执行eat之前,先执行 沐浴更衣 这个动作.

2.2、实现思路:

1.搭建基本的测试 可以在测试类中执行eat方法
2.创建切面类,指明对eat方法进行增强;

目标类:Dog

@Component
public class Dog {
public void eat() {
System.out.println(" aop dog 正在吃…");
}
}

配置类:

@Configuration
@ComponentScan(basePackages = {“com.czxy.demo15_aop.domain”,“com.czxy.demo15_aop.aop”})
public class Demo15Configuration {
}

测试类

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Demo15Configuration.class)
public class TestDemo15 {
@Resource
private Dog dog;
@Test
public void testDemo15() {
dog.eat();
}
}

修改配置类,开启AOP编程

@EnableAspectJAutoProxy //开启AOP

  • 编写切面类 MyAspect,对目标类的方法进行增强

@Component //将当前类,添加到spring容器中
@Aspect //切面编程注解
public class MyAspect {
// 切入点表达式: 方法签名
// @注解(“execution(返回值类型 包名.类名.方法名(参数类型))”)
@Before(“execution(void com.czxy.demo15_aop.domain.Dog.eat())”)
public void init() {
System.out.println(" 15 初始化");
}
}

3、AOP作用和优势

  • 作用:
    1.在程序运行期间,不修改源码对已有方法进行增强。

  • 优势:
    1.减少重复代码
    2.提高开发效率
    3.维护方便

4、 入门案例2

4.1、需求

使用AOP 对UserService接口的两个方法进行增强. 在方法执行之前,开启事务,在方法执行之后关闭事务.
目标类:

@Repository
public class UserDao {
public void insertUser() {
System.out.println(“添加”);
}
public void updateUser() {
System.out.println(“更新”);
}
}

配置类

@Configuration
@ComponentScan(basePackages = {“com.czxy.demo16_aop”})
@EnableAspectJAutoProxy //开启AOP
public class Demo16Configuration {
}

测试类

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Demo16Configuration.class)
public class TestDemo16 {
@Resource
private UserDao userDao;
@Test
public void testDemo15() {
userDao.insertUser();
System.out.println("----------");
userDao.updateUser();
}
}

切面类

@Component
@Aspect
public class MyAspect {
@Before(“execution(void com.czxy.demo16_aop.dao.UserDao.*User())”)
public void start() {
System.out.println(“开启事务”);
}
@After(“execution(void com.czxy.demo16_aop.dao.UserDao.*User())”)
public void commit() {
System.out.println(“提交事务”);
}
}

5、AOP实现方法

Spring AOP 主要通过2种代理技术来实现:JDK动态代理、CGLIB动态代理

  • JDK动态代理:用于对接口+实现类情况进行代理。

@EnableAspectJAutoProxy(proxyTargetClass = false)

  • CGLIB:用于对仅有类情况进行代理

@EnableAspectJAutoProxy(proxyTargetClass = true)

经过某实践者测试Jdk动态代理的性能强于CGLIB,所以Spring会默认使用JDK动态代理。

6、相关AOP术语

Target(目标对象):
代理的目标对象。
例如:UserServiceImpl
Joinpoint(连接点):
程序的某个特定位置,比如类开始初始化前,初始化后,方法调用前后,抛出异常前后等。
例如:eat方法调用前后
Pointcut(切入点):
基于连接点,链接点描述的可以增强的点,如果真的在这个点增强了,那这个点就叫做切入点。
例如:eat方法调用之前如果进行了增强,那这个点就叫做切入点
Advice(通知/增强):
需要添加的那段增强功能的逻辑代码,
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
例如:要在eat之前添加 wash,之后添加clean ,那wash和clean就是增强
Aspect(切面):
是切入点和通知的结合。
例如:MyAspect类
Proxy(代理):
一个类被AOP织入增强后,就产生一个结果代理类。
织入:
增强添加到目标类的具体链接点上的过程。

7、相关注解

7.1、切入点表达式

execution:
匹配方法的执行(常用)
execution(表达式)
表达式语法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
写法说明:
全匹配方式:
public void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
访问修饰符可以省略
void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
返回值可以使用号,表示任意返回值
* com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
包名可以使用
号,表示任意包,但是有几级包,需要写几个*
* ....CustomerServiceImpl.saveCustomer()
使用…来表示当前包,及其子包
* com…CustomerServiceImpl.saveCustomer()
类名可以使用号,表示任意类
* com…
.saveCustomer()
方法名可以使用号,表示任意方法
* com…
.()
参数列表可以使用
,表示参数可以是任意数据类型,但是必须有参数
* com….()
参数列表可以使用…表示有无参数均可,有参数可以是任意类型
* com…
.(…)
全通配方式:
* .
(…)

7.2、通知方法

  • 方式1:没有参数形式

@Before(“execution(public void com.czxy.demo01.User.eat())”)
public void bf01(){
System.out.println("洗手 ");
}

  • 方式2:获得参数JoinPoint,从而获得目标类,目标方法等信息

import org.aspectj.lang.JoinPoint;

@Before(“execution(public void com.czxy.demo01.User.eat())”)
public void bf01(JoinPoint jp){
System.out.println("洗手 ");
System.out.println(“目标类:”+jp.getTarget());//获取目标类
System.out.println(“切入点:”+jp.getSignature());//获取切入点

执行结果

  • 方式3:环绕通知获得参数ProceedingJoinPoint,对目标方法的执行进行控制。

@Around(“execution(public void com.czxy.demo01.User.eat())”)
public void ar(ProceedingJoinPoint jp) throws Throwable {
System.out.println("洗手 ");
jp.proceed();//执行 eat方法
System.out.println(“擦嘴”);
}

执行效果:

7.3、抽取公共切入点

使用@PointCut可以将公共的切入点进行抽取,一般都声明在私有方法上。
在通知注解使用,通过方法名引用。

@Pointcut(“execution(* com.czxy.service….(…))”)
private void myPointcut(){
}
@Before(“myPointcut()”)
public void bf(JoinPoint joinPoint){
System.out.println(“前置…” + joinPoint.getTarget());
System.out.println(“前置…” + joinPoint.getSignature().getName());
}
@AfterReturning(“myPointcut()”)
public void af(){
System.out.println(“后置…”);
}

8、完整通知演示

8.1、AOP编程

  • 编写需要对目标类,增量的类和方法(可以复制)

@Component
@Aspect
public class MyAspect {
@Before(“execution(* com.czxy.service….(…))”)
public void bf(){
System.out.println(“开始”);
}
@AfterReturning(“execution(* com.czxy.service….(…))”)
public void af(){
System.out.println(“结束”);
}
}

  • 修改配置类

@ComponentScan(basePackages={“com.czxy”})
@EnableAspectJAutoProxy
public class SpringConfigruation {
}

  • 测试

8.2、目标接口和类

  • 接口

public interface UserService {
public void saveUser();
public String updateUser();
}

  • 实现类

@Service
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println(“save”);
}
@Override
public String updateUser() {
System.out.println(“update”);
return “abc”;
}
}

8.3、配置类

@ComponentScan(basePackages={“com.czxy”})
@EnableAspectJAutoProxy
public class SpringConfigruation {
}

8.4、切面类

// 切面类也要交给IOC
@Component
// 声明当前类是切面类
@Aspect
public class PersonAspect {
// 抽取公共切入点
@Pointcut(“execution(public String com.czxy.domain.Person.eat())”)
public void pc1(){
}
@Before(“pc1()”)
public void b01(){
System.out.println("洗手手 ");
}
// 环绕通知 在 eat前后都会增强
@Around(“pc1()”)
public Object ar(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(“洗手”);
// 让目标方法 执行 也就是 eat执行
Object obj= pjp.proceed();
System.out.println(“擦嘴”);
// 环绕通知完, 把 目标方法的返回值 返回。 这样 @AfterReturning才能捕获到结果
return obj;
}
@After(“pc1()”)
public void a01(){
System.out.println(“盘子舔干净”);
}
@AfterReturning(value = “pc1()”,returning = “rel”)
public void a02(JoinPoint joinPoint , String rel){
System.out.println("嘿嘿嘿 "+rel);
}
@AfterThrowing(value=“pc1()”,throwing=“ex”)
public void at(JoinPoint joinPoint ,Throwable ex){
System.out.println(“异常:” + ex.getMessage());
}
}

8.5、测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
@Resource
private UserService userService;
@Test
public void testFindAll() throws SQLException{
userService.saveUser();
int i = 1/0;
userService.updateUser();
}
}

❤️‍Spring从入门到大神--AOP从入门到精通相关推荐

  1. spring3.2入门到大神(备java基础、jsp、servlet,javaee精髓)-任亮-专题视频课程

    spring3.2入门到大神(备java基础.jsp.servlet,javaee精髓) 课程介绍         框架介绍,IoC思想.DI依赖注入.Bean的实例方式.Bean种类.Bean作用域 ...

  2. Activiti 工作流入门到大神-任亮-专题视频课程

    Activiti 工作流入门到大神-16384人已学习 课程介绍         什么是流程.工作流作用.Activiti背景简介.Activiti流程设计器安装.Activity环境搭建.通过Hel ...

  3. python从入门到大神系列手机_python从入门到大神---2、和Python编程相遇的日子

    python从入门到大神---2.和Python编程相遇的日子 一.总结 一句话总结: python2和python3是很不同的,连语法都不同,比如 print 函数打印结果 1.python中pip ...

  4. python从入门到大神---4、python3文件操作最最最最简单实例

    python从入门到大神---4.python3文件操作最最最最简单实例 一.总结 一句话总结: python文件操作真的很简单,直接在代码中调用文件操作的函数比如open().read(),无需引包 ...

  5. python代码少的作品_原创 8行python代码展示程序员从入门到大神(或跑路)的全部状态...

    一行python代码可以做什么? 人生苦短,我用python.python的世界里无处不在的简洁和短小,往往一行代码可以实现很多有意思功能. 你敢想象你从入门python代码.网络达人.反重力怪才.爱 ...

  6. 8行python代码展示程序员从入门到大神(或跑路)的全部状态

    一行python代码可以做什么? 人生苦短,我用python.python的世界里无处不在的简洁和短小,往往一行代码可以实现很多有意思功能. 你敢想象你从入门python代码.网络达人.反重力怪才.爱 ...

  7. python类中的属性分为类属性和实例属性两种_python从入门到大神---1、初始化实例、类属性、方法...

    python从入门到大神---1.初始化实例.类属性.方法 一.总结 一句话总结: 方法不加括号是代码段:感觉python方法和js,php很类似,不加括号是代码段,加括号变成方法,比如f,f() 1 ...

  8. oracle入门到大神(备mysql、java基础、javaee必经之路)-任亮-专题视频课程

    oracle入门到大神(备mysql.java基础.javaee必经之路)-19178人已学习 课程介绍         Oracle10g的安装.orcale的基本概念介绍.命令行常用操作.Scot ...

  9. css入门到大神-任亮-专题视频课程

    css入门到大神-5713人已学习 课程介绍         CSS介绍.CSS导入方式(内部样式表.内联样式表.外部样式表).五大CSS选择器(ID选择器.类选择器.元素选择器.属性选择器.伪类等) ...

最新文章

  1. php 添加行_php 多行数据同时插入
  2. freebsd系统/: write failed, filesystem is full问题解决办法
  3. 诺基亚塞班系列最强回顾(搬运整理)
  4. CTF大赛学习第一天!!!(学习中)
  5. Oracle RESETLOGS 和 NORESETLOGS 区别说明
  6. Oracle执行外部文件:
  7. wget在线扒站网站程序源码
  8. (转) C# Async与Await的使用
  9. mysql 查看表属性约束_mysql表属性、索引、约束
  10. python3扬州大学校园网认证登录与下线
  11. web应用开发相关技术,CSS盒模型概述
  12. 人家这才叫软件测试工程师,你那只是混口饭吃(附HR面试宝典)
  13. 在Office的Excel中打开WPS很慢
  14. java移动端部署_飞桨实战笔记:自编写模型如何在服务器和移动端部署
  15. javascript eval 函数作用
  16. HTML5+CSS3小实例:不偷看密码的超萌猫头鹰登录界面
  17. 交换机工作原理及实验分析
  18. 获得手机上的软件名称 软件图标 软件包名
  19. Pandas-数据结构-DataFrame(七):添加元素、修改元素、删除元素
  20. 红石外汇|每日汇评:鲍威尔讲话助推黄金走出困境

热门文章

  1. 翻译Deep Learning and the Game of Go(14)第十二章 采用actor-critic方法的强化学习
  2. 阿里云的互联网方法论
  3. 计算机本地用户和组系统管理员,【判断题】你是一台Windows Server 2008计算机的系统管理员,你可以使用本地用户和组工具来管理该计算机中的组账号。...
  4. 依楼听风雨,淡看江湖路
  5. red hat 6 安装php,Red Hat Enterprise Linux 6安装图解
  6. git 如何查看远程分支
  7. 绝缘子泄漏电流在线监测装置
  8. 爪爪博士:入秋遛狗需要注意的一些问题
  9. SAP BW4 405(主要是query和bo)学习6-10章
  10. python编写程序输入球的半径计算球的表面积和体积_编写程序,计算球的表面积和体积。从键盘上输入球的半径,输出球的表面积和体积。...