Spring中的IOC做什么用的,原理是什么?

1.控制反转(Inversion of Control)与依赖注入(DependencyInjection)
控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:<1>依赖查找(Dependency Lookup): 容器提供回调接口和上下文环境给 组件。EJB和Apache Avalon都使用这种方式。<2>依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型,其又有接口注入(InterfaceInjection),设值注入(SetterInjection)和构造子注入(ConstructorInjection)三种方式。
图1 控制反转概念结构
依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造子或者接口,使容器可以在初始化时组装 对象的依赖关系。其与依赖查找方式相比,主要优势为:<1>查找定位操作与应用代码完全无关。<2>不依赖于容器的API,可以很容易地在任何容器以外使用应用对象。<3>不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。
 
2.好莱坞原则
IoC体现了好莱坞原则,即“不要打电话过来,我们会打给你”。第一次遇到好莱坞原则是在了解模板方法(Template Mathod)模式的时候,模板方法模式的核心是,基类(抽象类)定义了算法的骨架,而将一些步骤延迟到子类中。
图2 模板方法模式类图
 
现在来考虑IoC的实现机制,组件定义了整个流程框架,而其中的一些业务逻辑的实现要借助于其他业务对象的加入,它们可以通过两种方式参与到业务流程中,一种是依赖查找(Dependency Lookup),类似与JDNI的实现,通过JNDI来找到相应的业务对象(代码1),另一种是依赖注入,通过IoC容器将业务对象注入到组件中。
 
3. 依赖查找(Dependency Lookup)
下面代码展示了基于JNDI实现的依赖查找机制。
public class MyBusniessObject{
  private DataSource ds;
  private MyCollaborator myCollaborator;
 
  public MyBusnissObject(){
Context ctx = null;
try{
    ctx = new InitialContext();
    ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);
    myCollaborator =
 (MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);
    }……
代码1依赖查找(Dependency Lookup)代码实现
依赖查找的主要问题是,这段代码必须依赖于JNDI环境,所以它不能在应用服务器之外运行,并且如果要用别的方式取代JNDI来查找资源和协作对象,就必须把JNDI代码抽出来重构到一个策略方法中去。
 
4. 依赖注入(Dependency Injection)
依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。
下面分别演示3中注入机制。
代码 2 待注入的业务对象 Content.java
package com.zj.ioc.di;
 
publicclass Content {
 
    publicvoid BusniessContent(){
       System. out .println( "do business" );
    }
   
    publicvoid AnotherBusniessContent(){
       System. out .println( "do another business" );
    }
}
MyBusniess类展示了一个业务组件,它的实现需要对象Content的注入。代码3,代码4,代码5,6分别演示构造子注入(ConstructorInjection),设值注入(SetterInjection)和接口注入(InterfaceInjection)三种方式。
 
代码 3构造子注入(Constructor Injection) MyBusiness.java
package com.zj.ioc.di.ctor;
import com.zj.ioc.di.Content;
 
publicclass MyBusiness {
    private Content myContent ;
 
    public MyBusiness(Content content) {
       myContent = content;
    }
   
    publicvoid doBusiness(){
       myContent .BusniessContent();
    }
   
    publicvoid doAnotherBusiness(){
       myContent .AnotherBusniessContent();
    }
}
 
代码 4设值注入(Setter Injection) MyBusiness.java
package com.zj.ioc.di.set;
import com.zj.ioc.di.Content;
 
publicclass MyBusiness {
    private Content myContent ;
 
    publicvoid setContent(Content content) {
       myContent = content;
    }
   
    publicvoid doBusiness(){
       myContent .BusniessContent();
    }
   
    publicvoid doAnotherBusiness(){
       myContent .AnotherBusniessContent();
    }
}
 
代码 5 设置注入接口 InContent.java
package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;
 
publicinterface InContent {
    void createContent(Content content);
}
 
代码 6接口注入(Interface Injection) MyBusiness.java
package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;
 
publicclass MyBusiness implements InContent{
    private Content myContent ;
 
    publicvoid createContent(Content content) {
       myContent = content;
    }
   
    publicvoid doBusniess(){
       myContent .BusniessContent();
    }
   
    publicvoid doAnotherBusniess(){
       myContent .AnotherBusniessContent();
    }
}
 
5.依赖拖拽(Dependency Pull)
最后需要介绍的是依赖拖拽,注入的对象如何与组件发生联系,这个过程就是通过依赖拖拽实现。
代码7 依赖拖拽示例
public static void main(String[] args) throws Exception{
//get the bean factory
BeanFactory factory = getBeanFactory();
MessageRender mr = (MessageRender) factory.getBean(“renderer”);
mr.render();
}
而通常对注入对象的配置可以通过一个xml文件完成。
使用这种方式对对象进行集中管理,使用依赖拖拽与依赖查找本质的区别是,依赖查找是在业务组件代码中进行的,而不是从一个集中的注册处,特定的地点执行。
读了这篇文章,感觉写的很透彻,理解起来也很容易,谢谢笔者撰写的这篇文章。

本文出自 “子 孑” 博客,请务必保留此出处http://zhangjunhd.blog.51cto.com/113473/126530



<think>嗯,用户问的是Spring Framework中IoC和AOP的实现原理。我需要先回忆一下相关知识,然后组织语言回答。 首先,IoC,也就是控制反转,是Spring的核心。它的主要实现方式是依赖注入(DI)和依赖查找Spring通过BeanFactory和ApplicationContext来管理Bean的生命周期和依赖关系。具体来说,Bean的定义通常通过XML配置文件或者注解(比如@Component、@Autowired)来声明,容器在启动时会读取这些配置,创建Bean实例,并注入所需的依赖。可能还需要解释Bean的创建过程,比如反射机制的使用,以及如何解决循环依赖的问题。 然后是AOP,面向切面编程。Spring AOP主要使用动态代理来实现。如果有接口的话,会用JDK动态代理;没有接口的话,就用CGLIB库生成子类代理。切面通过@Aspect注解定义,切入点表达式指定在哪些方法执行时应用通知(Advice),比如@Before、@After等。需要提到AOP的应用场景,比如日志、事务管理,以及其实现的底层机制,比如在运行时生成代理对象,将切面逻辑织入到目标方法中。 用户可能希望了解两者的实现细节,比如具体的代码例子或者设计模式的应用。比如,IoC容器如何实例化Bean,如何解析依赖关系;AOP的代理对象是如何生成的,通知是如何被调用的。此外,可能需要区分Spring AOP和AspectJ的区别,以及各自的优缺点。 在回答时,应该先分别解释IoC和AOP的概念,再深入其实现机制。对于IoC,重点在于容器的管理机制和依赖注入的方式;对于AOP,则要说明动态代理和切面织入的过程。然后给出相关的代码示例,比如Bean的定义和注入,以及AOP的切面使用。 最后,相关的问题可能涉及Bean的作用域、循环依赖的解决、动态代理的选择条件、AOP的术语(如切入点、通知类型)等。要确保问题覆盖用户可能进一步询问的知识点。</think><< **Spring Framework中IoC和AOP的实现原理** ### 1. IoC控制反转)的实现原理 **核心机制**: IoC通过**依赖注入(DI)**和**依赖查找**实现,将对象的创建和依赖管理交给Spring容器。 **实现方式**: - **BeanFactory与ApplicationContext**: Spring通过`BeanFactory`接口及其实现类(如`DefaultListableBeanFactory`)管理Bean的生命周期,`ApplicationContext`是其扩展,提供更多企业级功能。 - **Bean定义与注册**: Bean的定义通过XML、注解(如`@Component`、`@Bean`)或Java配置类声明,容器启动时解析这些配置并注册到`BeanDefinitionRegistry`。 - **依赖注入**: 通过反射或CGLIB动态代理创建Bean实例,并通过构造器注入、Setter注入或字段注入(如`@Autowired`)完成依赖关系绑定。 **代码示例(依赖注入)**: ```java // 通过@Component注解声明Bean @Component public class UserService { @Autowired private UserRepository userRepository; } // 配置类扫描Bean @Configuration @ComponentScan("com.example") public class AppConfig {} ``` ### 2. AOP(面向切面编程)的实现原理 **核心机制**: AOP通过**动态代理**在运行时将横切逻辑(如日志、事务)织入目标方法。 **实现方式**: - **动态代理类型**: - **JDK动态代理**:基于接口,通过`Proxy`类生成代理对象。 - **CGLIB代理**:基于子类继承,用于无接口的类(需`@EnableAspectJAutoProxy(proxyTargetClass = true)`)。 - **切面定义**: 通过`@Aspect`注解定义切面,使用`@Pointcut`定义切入点,`@Before`/`@After`等定义通知。 - **织入过程**: Spring在Bean初始化后,通过`BeanPostProcessor`(如`AnnotationAwareAspectJAutoProxyCreator`)创建代理对象,将通知逻辑插入目标方法。 **代码示例(AOP切面)**: ```java @Aspect @Component public class LoggingAspect { @Pointcut("execution(* com.example.service.*.*(..))") public void serviceMethods() {} @Before("serviceMethods()") public void logBefore(JoinPoint joinPoint) { System.out.println("Method called: " + joinPoint.getSignature()); } } ``` ### 原理解释 - **IoC**:将对象控制权从代码转移到容器,降低耦合,通过反射和工厂模式实现依赖管理。 - **AOP**:通过代理模式分离横切关注点,动态生成代理类将切面逻辑与业务逻辑解耦。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值