AOP基本知识

知识点1:概念

  • AOP:面向切面编程,利用AOP可以对业务逻辑的各个部分隔离开,降低代码的耦合度,提高可复用性。
  • 个人理解:不修改源代码,而是在主干功能里添加新的功能,很想设计模式中的装饰者设计。

知识点2:底层原理

  1. 使用到了动态代理
  • 情况一:有接口,使用JDK动态代理;-->创建接口实现类代理对象,增强类的方法
  • 情况二:无接口,使用CGLIB动态代理。-->创建子类的代理对象,增强类的方法

知识点3: JDK动态代理实现

代码:

package com.guodaxia.AOP.dao;
//接口
public interface UserDao {
int add(int a,int b);
int id(int id);
}
//实现类
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public int id(int id) {
id +=1;
return id;
}
}

代理类

package com.guodaxia.AOP.dao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Objects;
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类代理对象
//实现类的接口
Class[] interfaces = {UserDao.class};
//第三个参数:代理类的接口InvocationHandler对象,由于接口不能直接创建对象,这里使用匿名内部类
UserDao dao= (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
//将旧的业务逻辑对象传递
//匿名内部类不允许有构造方法,写一个静态代码块,
// 在静态代码块new想要代理的对象,把他赋值给代码块外部的变量
UserDao userDao;
{
Objects obj;
userDao = new UserDaoImpl();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("方法之前执行..." + method.getName() + ":传递的参数..." + Arrays.toString(args));
//增强业务逻辑中
Object res = method.invoke(userDao, args);
System.out.println("方法之后执行..." + method.getName() +":"+ res);
return res;
}
});
int result = dao.add(1,1);
System.out.println(result);
System.out.println("-----------------");
int id = dao.id(006);
System.out.println(id);
}
}

总结

  1. 动态代理的好处在于可以在源代码的基础上,实现添加新功能;
  2. java包下有Proxy类用于用于创建代理;
  3. newProxyInstance(classLoad,interfaces,增强业务类)。

知识点3:术语

  1. 连接点:能够被增强的方法;
  2. 切入点:实际被增强的方法;
  3. 通知(增强):实际增强的逻辑部分,如日志更新,事务;

通知类型:

  • 前置通知
  • 后置通知
  • 环绕通知
  • 异常通知
  • 最终通知
  1. 切面:把通知应用到切入点的过程。

知识点4:AOP操作

准备

  • 使用AspectJ框架+spring框架完成AOP操作
  • 导入依赖

aop的jar包:

[com.springsource.net.sf.cglib-2.2.0.jar](......\dataFile\spring5\资料\资料\2 其他jar包\aop的jar包\com.springsource.net.sf.cglib-2.2.0.jar)

[com.springsource.org.aopalliance-1.0.0.jar](......\dataFile\spring5\资料\资料\2 其他jar包\aop的jar包\com.springsource.org.aopalliance-1.0.0.jar)

[com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar](......\dataFile\spring5\资料\资料\2 其他jar包\aop的jar包\com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar)

spring的jar包:

spring-aspects-5.2.6.RELEASE.jar

  • 切入点的表达式:知道对哪个类里面的 哪个方法进行增强。
  • 切入点语法结构:execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])

@Aspect注解**

步骤:

  1. 创建需要被增强的类和方法;
//被增强的类
@Component
public class User {
//被增强的方法
public void add(){
System.out.println("add..........");
}
}
  1. 创建增强类,并编写增强业务逻辑代码;
//增强的类
@Component
@Aspect
public class UserProxy {
//不同的方法代表着不同通知类型
//1. 前置通知
@Before(value = "execution(* com.guodaxia.AOP.aopaspect.User.add())")
public void before(){
System.out.println("before.........");
}
//2. 后置通知
//3. 环绕通知
//4. 异常通知
//5. 终止通知
}
  1. xml开启注解扫描 or 创建配置类开启注解扫描;
<?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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">
<!--开启注解扫描-->
<context:component-scan base-package="com.guodaxia.AOP.aopaspect"></context:component-scan>
</beans>
  1. 使用四大注解任何一个创建User和UserProxy对象;

  2. 在增强类上面添加注解@Aspect,自动生成代理对象;

  3. 在spring配置中开启生成代理对象;

  4. 配置不同类型的通知

  • 即在增强类中的方法上方添加通知类型注解,使用切入点表达式配置。
//不同的方法代表着不同通知类型
//1. 前置通知
@Before(value = "execution(* com.guodaxia.AOP.aopaspect.User.add())")
public void before(){
System.out.println("before.........");
}
//2. 后置通知
@After(value = "execution(* com.guodaxia.AOP.aopaspect.User.add())")
public void after(){
System.out.println("after .......");
}
//5. 最终通知
@AfterReturning(value = "execution(* com.guodaxia.AOP.aopaspect.User.add())")
public void afterReturning(){
System.out.println("afterReturning .......");
}
//3. 环绕通知
@Around(value = "execution(* com.guodaxia.AOP.aopaspect.User.add())")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Around before,,,,");
pjp.proceed();//被增强的方法执行
System.out.println("Around after......");
}
//4. 异常通知
@AfterThrowing(value = "execution(* com.guodaxia.AOP.aopaspect.User.add())")
public void afterThrowing(){
System.out.println("AfterThrowing .......");
}

执行结果

Around before,,,,
before.........
add..........
Around after......
after .......
afterReturning .......

总结:

  1. 一步一步慢慢来,分开配置,总能分解一个复杂的问题,总能汇成解决一个复杂的问题。
  2. 有些bug很小,跟着步骤一步一步检验,总能找到问题所在。
posted @   gdxstart  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示