Spring框架-AOP核心
Spring AOP
AOP (Aspect Oriented Programming) 面向切面编程
OOP(Object Oriented Programming)面向对象编程,用对象的思想来完善程序
AOP是的OOP的一个补充,是在另外一个维度上抽象出的对象。
具体是指程序运行时动态的将非业务代码切入到业务代码中,从而实现程序的解耦合,将非业务抽象成一个对象,对对象编程就是面向对象编程。
在同样的地方有相同的方法抽象成一个切面----代码A切面对象。
AOP的优点:
可以降低模块之间的耦合性
提高代码的复用性
集中管理代码的维护性
集中管理代码的非义务代码,便于维护
业务代码不受非业务代码的影响,逻辑更加清晰
理解AOP
创建接口的计算器类
java
package com.southwind.aop;
public interface Cal {
public int add(int num1,int num2);
public int sub(int num1,int num2);
public int mul(int num1,int num2);
public int div(int num1,int num2);
}
2.实现类:
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
}
@Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
}
@Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}
3.日志打印:
在每个方法开始的位置输出参数的信息
在每个方法的结束的位置输出结果信息
对于计算器而言,加减乘除是业务代码,日志是非业务代码。
AOP如何实现?:
使用动态代理
代理首先具备CaLImpl的基础功能,然后在这个基础上扩展日志功能
删除CalImpl方法中的打印日志的代码,只保留业务代码
创建MyinvocationHandler类,实现IvocationHandler接口,生成动态代理类
动态代理类要动态生成。
ClassLoader用来将动态的类加载到虚拟机(JVM)中。
Proxy.newProxyInstance(类加载器《object.getClass.getClassLoder》,委托对象的接口《object.getClass().getInterfaces()》,this);
动态创建代理类---方到实体类里面。
底层原理
1.接口:
```java
package com.southwind.aop;
public interface Cal {
public int add(int num1,int num2);
public int sub(int num1,int num2);
public int mul(int num1,int num2);
public int div(int num1,int num2);
}
2.代理对象:
package com.southwind.aop;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class MyinvocationHandler implements InvocationHandler {
//委托对象
private Object object=null;
//返回代理对象
public Object bind(Object object){
this.object=object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//实现业务代码和非业务代码调用
System.out.println(method.getName()+"方法的参数是:"+ Arrays.toString(args));
Object result=method.invoke(this.object,args);
System.out.println(method.getName()+"方法的参数是:"+ result);
return result;
}
}
```
3.实现类;
```java
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
}
@Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
}
@Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}
4.测试类:
```java
package com.southwind.test;
import com.southwind.aop.Cal;
import com.southwind.aop.MyinvocationHandler;
import com.southwind.aop.impl.CalImpl;
public class Test10 {
public static void main(String[] args) {
//实例化委托对象
Cal cal = new CalImpl();
// cal.add(10,3);
// cal.div(10,3);
// cal.mul(10,3);
// cal.sub(10,3);
// 获取代理对象
MyinvocationHandler myinvocationHandler= new MyinvocationHandler();
Cal proxy=(Cal)myinvocationHandler.bind(cal);
proxy.add(10,3);
}
}
上述代码的动态机制实现了业务代码和非业务代码的解耦合,这是SpringAOP的底层实现机制,不要这么复杂,有更好的方式。
Spring AOP的开发步骤:
1.创建切面类:
package com.southwind.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Array;
import java.util.Arrays;
@Component
@Aspect
public class LogAspect {
@Before("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void before(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
String args= Arrays.toString((joinPoint.getArgs()));
System.out.println(name+"方法的参数是"+args);
}
@After("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void after(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法执行完毕");
}
@AfterReturning(value = "execution(public int com.southwind.aop.impl.CalImpl.*(..))",returning = "result")
public void afterReturn(JoinPoint joinPoint,Object result){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法执行完毕"+"结果是:"+result);
}
@AfterThrowing(value = "execution(public int com.southwind.aop.impl.CalImpl.*(..))",throwing = "ex")
public void afterTrowing(JoinPoint joinPoint,Exception ex){
String name= joinPoint.getSignature().getName();
System.out.println(name+"方法抛出异常"+ex);
}
}
2.委托类加上@Component
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
import org.springframework.stereotype.Component;
@Component
public class CalImpl implements Cal {
@Override
public int add(int num1, int num2) {
int result = num1+num2;
return result;
}
@Override
public int sub(int num1, int num2) {
int result = num1-num2;
return result;
}
@Override
public int mul(int num1, int num2) {
int result = num1*num2;
return result;
}
@Override
public int div(int num1, int num2) {
int result = num1/num2;
return result;
}
}
3.配置spring.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: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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 扫包-->
<context:component-scan base-package="com.southwind.aop"></context:component-scan>
<!-- 自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
3测试类:
package com.southwind.aop.impl;
import com.southwind.aop.Cal;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-aop.xml");
Cal cal = (Cal)applicationContext.getBean("a");
System.out.println(cal.add(10,3));
}
}
@Component 将切面类加载到IoC容器中
@Aspect 表示类是一个切面类
@Before 表示方法执行的时机,execution表示的是切入点是CallImpl中执行add方法之前执行日志方法
@AfterReturning,表示方法的执行时机是再业务方法返回结果:returning是将返回的业务代码的返回的形参
@AfterThrowing:表示方法执行是抛出的异常,throwing表示抛出的异常的处理形参
aop:aspectj-autoproxy ,Spring IoC容器会结合动态代理对象自动的生成代理对象,AOP底层就是通过动态代理对象来实现的。
AOP的概念:
切面对象;根据切面抽象出来的对象,Callmpl所有的方法中需要加入日志的部分,抽象成一个切面对象
通知:切面对象具体执行的代码,即具体的非业务代码,LoggerAspect对象打印日志的代码
目标;被横切的对象,即CallImpl将通知加入其中。
代理:切面对象、通知、目标混合之后的结果,即时我门使用JDK动态代理的机制创建对象
连接点;需要被横切的位置,即要通知要插入业务代码的具体位置
Spring框架-AOP核心的更多相关文章
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- Spring框架的核心功能之AOP技术
技术分析之Spring框架的核心功能之AOP技术 AOP的概述 1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的 ...
- 跟着刚哥学习Spring框架--AOP(五)
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- 控制反转是Spring框架的核心。
早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题.他总结出是依赖对象的获得被反转了.基于这个结论,他为控制反转创造了一个更好的名字:依赖注入.许多非凡的应用(比H ...
- spring框架aop用注解形式注入Aspect切面无效的问题解决
由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...
- Spring 框架的核心功能之AOP技术
1. AOP 的概述 AOP, Aspect Oriented Programming, 面向切面编程; 通过预编译方式和运行期动态代理实现程序功能的统一维护的技术; AOP 采取横向抽取机制,取代了 ...
- Spring框架的核心功能之AOP概述
1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程 * AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构 ...
- Spring框架——AOP代理
我们知道AOP代理指的就是设计模式中的代理模式.一种是静态代理,高效,但是代码量偏大:另一种就是动态代理,动态代理又分为SDK下的动态代理,还有CGLIB的动态代理.Spring AOP说是实现了AO ...
- Spring框架-AOP详细学习[转载]
参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...
- Spring框架 AOP面向切面编程(转)
一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...
随机推荐
- Karmada跨集群优雅故障迁移特性解析
摘要:在 Karmada 最新版本 v1.3中,跨集群故障迁移特性支持优雅故障迁移,确保迁移过程足够平滑. 本文分享自华为云社区<Karmada跨集群优雅故障迁移特性解析>,作者:Karm ...
- Go | 函数注意事项
细节汇总 函数的形参列表可以是多个,返回值列表也可以是多个 形参列表和返回值列表的数据类型,可以是值类型.也可以是引用类型 函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写表示该函数可以被本 ...
- JavaScript入门④-万物皆对象:Object
01.Object对象 Object 是 JavaScript 的一种 数据类型,它用于存储各种键值集合和更复杂的实体,是一组数据和功能的集合.JS中几乎所有对象都是继承自Object,Array.R ...
- day35-JSON&Ajax03
JSON&Ajax03 4.jQuery的Ajax请求 原生Ajax请求问题分析: 编写原生的Ajax要写很多的代码,还要考虑浏览器兼容问题,使用不方便 在实际工作中,一般使用JavaScri ...
- Go 快速入门指南 - 序言
这本书是写什么的? 这是一本 Go 语言快速入门手册,目标读者是有任一编程语言基础,希望以最快的时间 (比如一个周末) 入门 Go 语言. 这本书应该怎么读? 书中几乎没有较长篇幅的理论知识,更多的是 ...
- (已转)Linux基础第七章 线程
前言 之前讨论了进程,了解一个进程能做一件事情,如果想同时处理多件事情,那么需要多个进程,但是进程间很不方便的一点是,进程间的数据交换似乎没有那么方便.Linux提供线程功能,能在一个进程中,处理多任 ...
- Linu基础 文件IO(读写操作)
前言 本章讨论普通文件的读写.读写效率.简单介绍文件描述符.IO效率.文件共享和原子操作.dup.文件映射.临时文件. 文件描述符 在Linux系统中,打开的文件是用一个整数来表示的,表示打开文件的整 ...
- 【基础篇】一文带你掌握 Redis
一.摘要 谈起 Redis,相信大家都不会陌生,做过云平台开发的程序员多多少少会接触到它,Redis 英文全称:Remote Dictionary Server,也被称之为远程字典服务. 从官方的定义 ...
- Spring+Quartz+Dom4j实现一个小项目
目录 1.项目背景 2.技术介绍 3.实现代码 4.程序演示 5.打成jar包 1.项目背景 最近在工作中碰到了一个问题,一个叫aura的系统每天都会接收到许多xml,其中有些xml会包含错误信息,这 ...
- 火山引擎DataLeap数据调度实例的 DAG 优化方案
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,并进入官方交流群 实例 DAG 介绍 DataLeap 是火山引擎自研的一站式大数据中台解决方案,集数据集成.开发.运维.治理.资产管理能力 ...