Spring-AOP(面向切面编程)
在百度中的解释:
划重点!!!:
- AOP:意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
- AOP:是OOP的延续,是软件开发中的一个热点(跟上时代步伐)
- AOP:是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
拓展:
-
**AOP是一种思想:**AOP联盟:指定的AOP思想和实现的标准,是OOP的一种补充
-
SpringAOP:使用了aspect J切入点表达式
(Spring不排斥市场上优秀的开源框架,但是不重复造轮子)
将业务代码和非业务代码进行分离后整合,SpringAOP中需要进行一个代码级的横向切入,业务代码正常执行,不需要额外添加其他的内容。
将业务代码与非业务代码相关的代码进行分割,分割之后开发者只关心与业务相关代码,而非业务相关代码或处理有横向切入的方式将代码织入到程序中。
如何实现AOP
注:SpringAOP代理的对象必须是Spring托管的对象
- 开启AOP命名空间
<!-- 加入AOP命名空间 -->
xmlns:aop="http://www.springframework.org/schema/aop"
- 设置开启配置
<!-- 开启SpringAOP配置 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 扫描注解进行注册 -->
<context:component-scan base-package="com.yang"></context:component-scan>
- 类中加上注解
- @Aspect:设置为切面
- @Component:进行注册
可以统一设置切入点
@Pointcut("execution(* com.yang.service.*.*(..))")
public void path() {}
//前置通知
@Before("path()")
public void addBefore() {
System.out.println("执行前添加方法");
}
//后置通知
@After("path()")
public void after() {
System.out.println("后置切入执行");
}
SpringAOP有几种通知类型?
Spring AOP 中有 5 中通知类型,分别如下:
基于注解实现通知方式
//前置通知
@Before("execution(* com.yang.service.BookService.add())")
public void addBefore() {
System.out.println("执行前添加方法");
}
//后置通知
@After("execution(* com.yang.service.*.*(..))")
public void after() {
System.out.println("后置切入执行");
}
//异常通知
@AfterThrowing(value="execution(* com.yang.service.*.*(..))",throwing="ex")
public void exMethod(Exception ex) {
System.out.println("出现异常切入执行");
}
//最终通知
@AfterReturning(value="execution(* com.yang.service.*.*(..))",returning="obj")
public void finallyMethod(Object obj) {
System.out.println("最终切入执行");
}
//======性能强悍======
//环绕通知
@Around("path()")
public Object aroundMethod(ProceedingJoinPoint pjp) {
//可以设置方法在何时执行
Object obj = null;
System.out.println("开启事务");
try {
System.out.println("环绕增强");
//这个方法不调用 目标不执行
obj = pjp.proceed();
System.out.println("事务提交");
} catch (Throwable e) {
e.printStackTrace();
System.out.println("事务回滚");
}
String s = (String) obj;
s = "修改后的数据";
return s;
}
基于XML实现通知方法
<!-- 注解配置AOP -->
<!-- 切面类 -->
<bean id="aspectTest" class="com.yang.aspect.BookServiceAspect02"></bean>
<!-- 配置AOP通知类型方法声明 切入点 -->
<aop:config>
<!-- 设置切入点 -->
<aop:pointcut expression="execution(* com.yang.service.*.*(..))" id="myPointcut"/>
<!-- 针对哪种通知类型,使用哪种方法 -->
<aop:aspect ref="aspectTest">
<!-- 前置增强 -->
<aop:before method="addBefore" pointcut-ref="myPointcut"/>
<!-- 后置增强 -->
<aop:after method="after" pointcut-ref="myPointcut"/>
<!-- 异常增强 -->
<aop:after-throwing method="exMethod" throwing="ex" pointcut-ref="myPointcut"/>
<!-- 最终增强 -->
<aop:after-returning method="finallyMethod" returning="obj" pointcut-ref="myPointcut"/>
<!-- 环绕增强 -->
<aop:around method="aroundMethod" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
SpringAOP -JDK动态代理
-
JDK动态代理的特性
**JDK动态代理只提供接口的代理,不支持类的代理。**所以我们如果要使用JDK动态代理要让被代理的对象实现一个接口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHrZFDny-1619352723547)(C:\Users\Hasee\AppData\Roaming\Typora\typora-user-images\image-20210422171715687.png)]
-
UserService接口
在接口中定义一些基础性操作方法
package com.yang.service;
public interface UserService {
void save();
void update();
void delete();
}
- UserServiceImpl实现类
package com.yang.service.impl;
import com.yang.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("执行添加方法");
}
@Override
public void update() {
System.out.println("执行修改方法");
}
@Override
public void delete() {
System.out.println("执行删除方法");
}
}
- TranService接口
package com.yang.service;
public interface TranService {
void opentransaction();
void commit();
void rollback();
}
- TranServiceImpl实现类
package com.yang.service.impl;
import com.yang.service.TranService;
public class TranServiceImpl implements TranService {
@Override
public void opentransaction() {
System.out.println("开启事务");
}
@Override
public void commit() {
System.out.println("提交事务");
}
@Override
public void rollback() {
System.out.println("回滚事务");
}
}
- 动态代理类
package com.yang.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.yang.service.TranService;
public class DynamicProxy implements InvocationHandler {
private Object obj;
private TranService tranService;
//有参构造
public DynamicProxy(Object obj, TranService tranService) {
super();
this.obj = obj;
this.tranService = tranService;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//声明返回对象
Object object = null;
//开启事务
this.tranService.opentransaction();
try {
//委托后的方法调用
object = method.invoke(obj, args);
//事务提交
this.tranService.commit();
} catch (Exception e) {
//事务回滚
this.tranService.rollback();
}
return object;
}
}
- 运行测试类
package com.yang.run;
import java.lang.reflect.Proxy;
import com.yang.proxy.DynamicProxy;
import com.yang.service.TranService;
import com.yang.service.UserService;
import com.yang.service.impl.TranServiceImpl;
import com.yang.service.impl.UserServiceImpl;
public class RunTest {
public static void main(String[] args) {
//被代理的对象
UserService serviceImpl = new UserServiceImpl();
//事务对象
TranService tranServiceImpl = new TranServiceImpl();
//调用动态代理
UserService userService = (UserService) Proxy.newProxyInstance(serviceImpl.getClass().getClassLoader(),
serviceImpl.getClass().getInterfaces(),
new DynamicProxy(serviceImpl, tranServiceImpl));
//使用代理后的对象那个调用方法
userService.delete();;
}
}