面试十一、spring的AOP和IOC,底层原理
参考链接:https://blog.csdn.net/liyifan687/article/details/90678729
1、AOP
1.1、面向切面编程,可分为静态代理和动态代理
1.2、3个实现
AspectJ:静态代理,我们在编写一段独立业务代码时可以使用aspectj将逻辑加入
业务方法中(比如常用的操作日志记录),在编译后我们的class文件会
多出一段代码,这段代码就是aspectj在编译时增加的aop代码。这种做法可以称为静态代理
代理类在调用被代理类方法前后增加一些切面逻辑。
JDK动态代理:使用jdk的反射机制来完成aop的动态代理,有如下要求:
1)被代理类(我们实现业务的类)要实现统一接口
2)代理类要实现reflect包里面的InvacationHandler
3)通过jdk proxy提供的静态方法newProxyInstance(xxx)来动态创建代理类
注:proxy是jdk动态生成的代理类,和service属于同一个类,
但是save方法被动用时jdk为我们自动的实现类切面逻辑。
使用jdk反射机制,生成一个继承Proxy的代理类。实现了InvocationHandler接口,
在调用方法时实际会先经过invoke方法转发,所以可以在invoke方法上增加一些切面逻辑
1 // 统一接口 2 public interface IService { 3 void save(); 4 } 5 6 // 接口实现类 7 public class UserService implements IService{ 8 @Override 9 public void save() { 10 System.out.println("save a user ..."); 11 } 12 } 13 14 // 实现InvacationHandler 15 public class MyHandler implements InvocationHandler { 16 private Object target; 17 18 MyHandler(Object target) { 19 this.target = target; 20 } 21 //在这里实现我们的切面逻辑 22 @Override 23 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 24 System.out.println("before ..."); 25 Object result = method.invoke(target, args); 26 System.out.println("after ..."); 27 return result; 28 } 29 } 30 31 // 客户端代码 32 public static void main(String[] args) { 33 //创建被代理类 34 IService service = new UserService(); 35 //新建代理类,将被代理类注册到里面 36 MyHandler aop = new MyHandler(service); 37 //Proxy为MyHandler动态创建一个符合某一接口的代理实例 38 //第一个参数:获取被代理类的class loader 39 //第二个参数:获取被代理类实现的接口, 由此可见被代理类需要实现统一的接口 40 //第三个参数:InvocationHandler的实例, 也就是我们做切面逻辑的类 41 IService proxy = (IService) Proxy 42 .newProxyInstance(service.getClass().getClassLoader(), 43 service.getClass().getInterfaces(), 44 aop); 45 //调用代理方法 46 proxy.save(); 47 } 48 49 // 输出结果 50 before 51 save user 52 after
GGLIB:全称Code Generation LIbrary,代码生产库。
基于字节码技术,修改被代理类的.class文件生成代理类的子类,并重写了代理类的方法。
实现了MethodInterceptor接口,在interceptor方法里增加切面逻辑
1 // 定义被代理类 2 public class UserService{ 3 public void save() { 4 System.out.println("save a user ..."); 5 } 6 } 7 8 // 实现MethodInterceptor接口(切面逻辑) 9 public class UserProxy implements MethodInterceptor { 10 @Override 11 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 12 //方法执行前的逻辑 13 System.out.println("before ..."); 14 e 15 Object result = methodProxy.invokeSuper(o, objects); 16 //方法执行后的逻辑 17 System.out.println("after ..."); 18 return result; 19 } 20 } 21 22 // 获取被代理类工厂,该工厂专门生产加入了切面的被代理类 23 public class UserServiceFactory { 24 public static UserService getInstance(UserProxy proxy) { 25 Enhancer enhancer = new Enhancer(); 26 enhancer.setSuperclass(UserService.class); 27 //设置回调类,强化类调用回调类中的intercept方法来执行我们定义好的切面逻辑 28 enhancer.setCallback(proxy); 29 //返回一个添加了切面逻辑的增强类 30 return (UserService) enhancer.create(); 31 } 32 } 33 34 // 客户端调用 35 public static void main(String[] args) { 36 UserProxy proxy=new UserProxy(); 37 //通过工厂方法模式获取增强类 38 UserService service = UserServiceFactory.getInstance(proxy); 39 service.save(); 40 }
1.3、jdk动态代理和CGLIB区别
CGLIB是通过字节码技术,在程序运行时为类创建了一个子类,重写了父类的方法
并加入了切面逻辑(无法代理final方法)。
优点:继承原对象并重写方法,所有能代理普通类。
jdk动态代理是运用jdk反射机制,根据代理类和代理接口生成新的字节码,然后进行加载并生成
对象。
优点:生成代理类相对较快,
缺点:但是运行切面逻辑没有CGLIB快,且要实现统一接口扩展性较差。因为要继承Proxy类
所以只能代理接口类。
2、IOC
2.1、控制反转(获得依赖对象的方式被反转)
在业务中一般都需要至少两个对象来完成,那么通常情况下每个对象在使用时都需要new,
这样就导致对象之间的耦合度高了。IOC的思想就是Spring容器来实现这些相互依赖
对象的创建、协调,对象只需要关心业务逻辑本身就行了。
底层原理:反射技术
posted on 2021-08-26 23:02 Iversonstear 阅读(2376) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!