文章目录

  • 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. 分布式工具的一次小升级⏫
  2. 如何通过反射调用扩展方法?
  3. 洛谷——P1183 多边形的面积
  4. CCAI2018丨大会日程发布 聚焦AI展望未来
  5. 【MFC】Windows样式
  6. 新的C库Bionic的介绍
  7. mysql查询雇员部门和性别_数据库管理系统MySQL实验
  8. linux命令之tee,linux tee命令
  9. python语言能做什么-python语言可以干什么
  10. Wireshark系列之5 显示过滤器
  11. 5G无线关键技术 — 双工技术
  12. mac分区数据恢复|mac分区后数据丢失怎么恢复?
  13. 将RDL报表转换成RDLC报表的函数
  14. Codeforces Round #363 (Div. 2) B. One Bomb (水题)
  15. linux pam limits.so,Linux 无法本地登录解决方法 报错/lib/security/pam_limits.so
  16. Android 【工具类】
  17. pytorch的DP和DDP
  18. 【OpenCV入门学习--python】Anisotropic image segmentation by a gradient structure tensor
  19. 推荐一个Linux远程桌面工具
  20. android模拟器不能运行 控制台显示 VCPU shutdown request

热门文章

  1. Nginx从听说到学会
  2. 夏季南方去体内湿气-养生方法
  3. Sql Server 2008 数据库实时同步
  4. java dtw,DTW动态时间规整算法
  5. jquery的onload事件
  6. tpcc压测MySQL数据库
  7. 苹果IOS应用上架遇到的问题及处理方法记录
  8. cocos2dx3.4 new Lua项目后编译黑屏问题的解决
  9. 解决vivado2018.3 分析综合都没问题,但是生成比特流出错的问题
  10. 经常使用电脑易患焦虑抑郁症