AOP:aspect oriented programming 面向切面变成
aspect:方面,切面
oriented:面向
aop对我们oop的补充,对功能、日志、权限验证、参数验证
对于这些公共的功能,可以提取出来,然后通过一定的方式,在我们运行主业务(保存用户、下单、支付)代码的时候,把这些功能加进来
切面要做的就是不影响我们的主业务功能的情况下,新增一些辅助的功能。
ioc:控制反转
spring用的技术实现--DI(依赖注入)
底层技术:反射
aop:
技术实现:spring aop aspectj(第三方提供的面向切面功能)
底层技术:动态代理 代理:明星的经纪人,代你完成一些事
jdk提供的:必须有接口和实现类
目标对象:主业务方法(比如:新增功能)所在的对象(是接口的实现类)
代理对象:通过jdk创建一个代理,此代理和目标对象都有同样的接口(如:新增方法),可以认为目标对象的兄弟,即都实现了共同的接口
cglib:必须有继承关系
父类:目标对象:主业务方法所在的对象
子类:目标对象的子类
aop:新增的辅助功能是通过子类实现的
aop代理:一个主业务(保存用户信息),如果要加入一些别的辅助功能,那么因为不能修改我们的主业务方法,所以要有一个和我们主业务相同方法的对象,即是主业务方法所在对象的代理
Spring AOP面向切面编程
的底层是动态代理,只是更加规范了动态代理的代码,其实SpringAOP还是动态代理实现的
它整合了jdk和cglib动态代理,不需要我们开发人员再实现了
通过spring aop实现给主业务新增功能的两种方式:
xml
注解
spring AOP一些概念
连接点(JoinPoint):理论上是可以被新增功能(加强)的方法(如:UserDaoImpl中的add()、update()、find()方法)
切点(切入点):我们通过配置Spring AOP,要确确实实新增功能的方法,就是连接点组成的集合
通知(加强):用来给主业务新增的具体功能、方法(如:MyIn中调用LogUtil中的方法)
切面(aspect):通知/加强 + 切点
织入(weaving):把通知/加强注入到切点的过程(MyIn中调用LogUtil中的方法应用到UserDaoImpl中的add()、update()、find()方法)
OOP:object oriented programming 面向对象编
简单的例子演示aop给我们干了什么(使用jdk提供的)
package com.aop.dao;
/**
* @title: IUserDao
* @Author 尤词
* @Date: 2022/8/16 16:28
* @Description: 简单传创建一个接口,写一些方法
* @Version 1.0
*/
public interface IUserDao {
void add();
void update();
void find();
}
package com.aop.dao.impl;
import com.aop.dao.IUserDao;
/**
* @title: UserDaoService
* @Author 尤词
* @Date: 2022/8/16 16:29
* @Description: 实现类
* @Version 1.0
*/
public class UserDaoImpl implements IUserDao {
@Override
public void add() {
//将日志交给代理对象来做
// System.out.println("----操作 执行之前的日志----");
System.out.println("--------主业务 新增用户--------");
// System.out.println("----操作 执行之后的日志----");
}
@Override
public void update() {
// System.out.println("----操作 执行之前的日志----");
System.out.println("--------主业务 修改用户--------");
// System.out.println("----操作 执行之后的日志----");
}
@Override
public void find() {
// System.out.println("----操作 执行之前的日志----");
System.out.println("--------主业务 查询用户--------");
// System.out.println("----操作 执行之后的日志----");
}
}
package com.aop;
/**
* @title: LogUtil
* @Author 尤词
* @Date: 2022/8/16 17:10
* @Description: 工具类
* @Version 1.0
*/
public class LogUtil {
public static void before(){
System.out.println("----操作 执行之前的日志----");
}
public static void after(){
System.out.println("----操作 执行之后的日志----");
}
}
package com.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @title: MyIn
* @Author 尤词
* @Date: 2022/8/16 16:37
* @Description: 创建一个类继承InvocationHandler生成代理
* @Version 1.0
*/
public class MyIn implements InvocationHandler {
private Object target;//目标对象,此处就是被代理对象
public MyIn(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这里就相当于给主业务添加辅助功能
System.out.println("----操作 执行之前的日志----");
Object obj = method.invoke(target, args);
System.out.println("----操作 执行之后的日志----");
return obj;
}
}
package com.aop.test;
import com.aop.MyIn;
import com.aop.dao.IUserDao;
import com.aop.dao.impl.UserDaoImpl;
import org.junit.Test;
import java.lang.reflect.Proxy;
/**
* @title: JdkTest
* @Author 尤词
* @Date: 2022/8/16 16:31
* @Description: jdk代理对象的测试类
* @Version 1.0
*/
public class JdkTest {
@Test
public void fun1(){
IUserDao dao = new UserDaoImpl();
dao.add();
}
@Test
public void fun2(){
//目标对象
IUserDao dao = new UserDaoImpl();
/*
* jdk生成代理
* 1.实现InvocationHandler
* 2.通过Proxy类创建代理,Proxy是jdk提供的类
* */
MyIn myIn = new MyIn(dao);
//通过Proxy类创建代理
IUserDao o = (IUserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), myIn);
o.add();
System.out.println();
System.out.println();
o.update();
System.out.println();
System.out.println();
o.find();
}
}