Spring中IOC和AOP的实现原理

本文详细解析了Java中IOC(控制反转)与AOP(面向切面编程)的基本概念及其实现原理。介绍了IOC如何通过Spring容器管理和创建对象,以及AOP如何利用动态代理技术在业务逻辑前后加入通用功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IOC

java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,在使用其他的合作对象时,均要使用像new object() 这样的语法来完成合作对象的创建。而IOC的思想说白了就是由Spring容器来实现对象的创建管理工作。我们只需要关心业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)。

IOC是基于java的反射机制以及工厂模式实现的。具体可以看下这两篇文章,https://www.cnblogs.com/Eason-S/p/5851078.html和http://blog.youkuaiyun.com/liushuijinger/article/details/35978965,写的都很好

工场:各类都实现了某一接口,并提供一个工场类,根据传入参数的不同来创建不同的对象

反射:可以根据类名获取该类实例, Class.forName(ClassName).newInstance()

在项目启动时首先获取class 对应name和beanDefinition,然后通过beanDefinition创建实例,以类似键值对的方式将name和bean实例存储在spring上下文容器中,当需要使用时直接利用getBean(String beanName)从容器中获取对应的实例。

AOP主要是使用动态代理实现 https://www.cnblogs.com/lcngu/p/5339555.html,https://www.cnblogs.com/cenyu/p/6289209.html这个讲代理的也挺好

AOP(面向切面编程),在业务处理过程之前或之后总会有一些公共行为比如像权限认证、事务处理、打印日志等等,我们将那些公共行为封装到一个可重用模块,这些公共行为叫做切面,而被环绕的业务代码叫做切点,环绕切点的一系列操作均是对切点的增强处理

JDK动态代理(被代理的类需要实现一个接口):中使用InvocationHandler接口和Proxy类来实现,在InvocationHandler中的invoke(Proxy proxy,Method method, object arg[])方法,中处理日志,认证,事务等操作

//接口
public interface Fruit {
    void fruitName();
}

//实现类
public class AppleService implements Fruit {

    @Override
    public void fruitName() {
        System.out.println( "我是苹果");
    }
}


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理对象工场
public class ProxyFactory {

    private Object targect;

    public ProxyFactory(Fruit fruit) {
        targect = fruit;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(targect.getClass().getClassLoader(), targect.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("动态代理进来了");
                Object object =  method.invoke(targect, args);
                System.out.println("动态代理执行完了");
                return object;
            }
        });
    }

    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory(new AppleService());
        Fruit target = (Fruit) proxyFactory.getProxyInstance();
        target.fruitName();
    }
}

步骤:(1)构造InvocationHandler处理器,定义invoke()方法(2)获取Proxy代理类,并生成代理类对象,调用方法完成相关操作

Proxy.newProxyInstance()

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
newProxyInstance,方法有三个参数:

loader: 用哪个类加载器去加载代理对象

interfaces:动态代理类需要实现的接口

h:动态代理方法在执行时,会调用h里面的invoke方法去执行,invoke(Proxy proxy,Method method, object arg[])

静态代理:实现了被代理类接口的类,其中保存了一个被代理类的实例。在接口的实现方法中,调用被代理对象对应的方法,同时添加需要的其他操作。缺点:代理类和委托类都实现了同样的接口,代码重复;当需要对对不同的委托类实现相同的处理时,需要定义多个代理类

CGLIB动态代理:无论是静态代理还是动态代理都需要委托类实现接口,如果要对不实现接口的类进行代理,就需要使用cglib库,使用Enhancer来创建代理类,使用MethodIntercepter接口,重写intercept()方法,实现具体操作

//未实现接口
public class BananaService {
    public void fruitName() {
        System.out.println("我是香蕉");
    }
}

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyFactory {
    private Object target;

    public CglibProxyFactory(BananaService bananaService) {
        target = bananaService;
    }

    public Object getCglibProxyInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("cglib 动态代理进来了");
                Object value = method.invoke(target, objects);
                System.out.println("cglib 动态代理跑完了");
                return value;
            }
        });
        return enhancer.create();
    }

    public static void main(String[] args) {
        CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(new BananaService());
        BananaService proxy = (BananaService)cglibProxyFactory.getCglibProxyInstance();
        proxy.fruitName();
    }
}

Spring会根据具体的Bean是否具有接口去选择动态代理方式,如果有接口,使用的是Jdk的动态代理方式,如果没有接口,使用的是cglib的动态代理方式。

https://blog.youkuaiyun.com/zizila/article/details/83169005

<think>好的,我现在需要回答用户关于Spring框架中IOCAOP实现原理及源码解析的问题。首先,我需要回顾一下IOCAOP的基本概念,确保自己理解正确。然后,结合用户提供的引用内容,特别是引用3、4、5中的信息,深入分析源码流程。 首先,关于IOC(控制反转),用户提到在refresh方法中的finishBeanFactoryInitialization方法里进行Bean的初始化,这涉及到getBean方法。我需要解释Bean的加载过程,包括如何从配置文件解析到生成BeanDefinition,并注册到BeanFactory中。引用4中详细描述了XML配置文件的解析流程,从获取文件流到解析为BeanDefinition,并存储到BeanDefinitionMap中。这部分需要详细说明,可能需要分步骤讲解,比如加载配置、解析Bean定义、实例化Bean等。 接下来是AOP(面向切面编程)的实现原理。根据引用5,AOP的动态代理有两种方式:CGLIBJDK动态代理。需要解释AOP如何通过这两个技术实现,以及Spring如何选择使用哪一种。可能还需要提到AOP的核心类,比如AopProxy接口及其实现类,以及生成代理对象的过程。用户提供的代码示例中有getProxy方法,需要说明其作用。 然后,用户的问题还涉及源码分析,所以需要结合具体的源码流程,比如refresh()方法的调用链,BeanFactory的初始化步骤,以及AOP代理的创建时机。例如,在Spring容器启动时,如何触发Bean的创建,以及何时应用AOP增强。 还需要注意引用中提到的@Conditional注解组件扫描,这些可能涉及条件化Bean的注册,但用户的问题主要集中在IOCAOP原理,这部分可能不需要深入,除非与核心流程相关。 另外,用户提供的引用中有关于BeanDefinition的注册到BeanDefinitionMap的过程,这属于IOC容器管理Bean的关键步骤,需要解释清楚。同时,动态代理在AOP中的应用,如何拦截方法调用并织入切面逻辑,也是重点。 在组织回答时,需要分点说明IOCAOP原理,每个部分结合源码流程,引用对应的引用内容作为支持。例如,在IOC部分,可以分加载配置、解析Bean定义、实例化Bean等步骤;在AOP部分,可以分动态代理的选择、代理对象的生成、切面的织入等。 最后,生成的相关问题需要围绕用户可能感兴趣的扩展点,比如动态代理的选择条件、Bean的生命周期、AOP的应用场景等,确保问题与主题相关且有深度。 现在,需要检查是否有遗漏的细节,比如BeanFactoryApplicationContext的区别,或者具体的源码方法调用顺序。根据用户提供的引用,重点在refresh方法finishBeanFactoryInitialization,以及getBean的调用,这些需要明确提到。 总结一下,回答的结构应该是先介绍IOC原理源码流程,再介绍AOP原理实现方式,最后给出相关问题。确保每个部分都有引用支持,并且语言简洁明了,符合用户的要求。</think>### Spring IOCAOP实现原理及源码分析 #### 一、Spring IOC实现原理 **1. Bean定义加载与注册** Spring IOC的核心是通过`BeanDefinition`管理Bean的元信息。在容器启动时,Spring会解析配置文件(如XML或注解),将每个`<bean>`节点转换为`BeanDefinition`对象,并通过`BeanDefinitionRegistry`注册到`DefaultListableBeanFactory`的`BeanDefinitionMap`中[^4]。例如,XML解析过程通过`XmlBeanDefinitionReader`加载文件流,最终调用`parseBeanDefinitionElement`生成`BeanDefinition`[^4]。 **2. Bean实例化与依赖注入** 在容器初始化阶段,`refresh()`方法中的`finishBeanFactoryInitialization`会触发非懒加载Bean的实例化。此过程通过`getBean()`方法实现,包括: - **实例化**:通过反射或工厂方法创建Bean对象; - **属性填充**:自动注入依赖(如`@Autowired`); - **初始化**:调用`init-method`或`@PostConstruct`方法[^3]。 **3. 容器管理** 所有Bean实例最终由`DefaultSingletonBeanRegistry`管理,存储在`singletonObjects`缓存中,实现单例模式的生命周期管理[^3]。 --- #### 二、Spring AOP实现原理 **1. 动态代理机制** Spring AOP通过动态代理在运行时生成代理对象,分为两种方式: - **JDK动态代理**:基于接口,通过`JdkDynamicAopProxy`实现,要求目标类必须实现接口[^5]; - **CGLIB代理**:基于子类继承,通过`CglibAopProxy`生成目标类的子类代理,适用于无接口的类[^5]。 **2. 代理对象生成流程** - **切面解析**:通过`@Aspect`注解或XML配置定义切面逻辑; - **代理工厂**:`ProxyFactory`根据目标对象增强器(Advice)选择合适的代理方式; - **织入逻辑**:代理对象拦截方法调用,按顺序执行前置、后置、环绕等通知[^5]。 **3. 源码关键点** 在`AbstractAutoProxyCreator`中,`postProcessAfterInitialization`方法会在Bean初始化后判断是否需要生成代理对象,最终调用`getProxy()`方法创建代理。 --- #### 三、核心源码流程示例 **IOC容器初始化** ```java // Spring容器启动入口 AbstractApplicationContext.refresh() { // 加载BeanDefinition obtainFreshBeanFactory(); // 实例化单例Bean finishBeanFactoryInitialization(beanFactory); } ``` **AOP代理创建** ```java // 代理工厂选择代理方式 public class DefaultAopProxyFactory { public AopProxy createAopProxy(AdvisedSupport config) { if (config.isOptimize() || config.isProxyTargetClass()) { return new CglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值