Spring之IOC容器(带你一篇文章搞定IOC)

简介: Spring之IOC容器(带你一篇文章搞定IOC)



前言

Spring框架的核心就是IOC和AOP,本篇文章就讲述一下其中的IOC容器。(这是听尚硅谷课程总结的)


一、IOC概述及底层原理

1.概述和原理

  • IOC是控制反转的意思。使用对象时候由主动new对象转换成由外部提供对象,此过程中对象的创建权由程序转移到外部,这种思想叫做控制反转。即把对象创建和对象的调用过程交给spring进行管理。
  • 目的:降低耦合度。
  • 底层原理:xml配置,反射,工厂模式。
  • Spring提供IOC容器两种实现方式(两个接口)
    (1)BeanFactory:Spring内部使用的接口,不提倡开发人员使用。特点:加载配置文件时不会创建对象,获取对象时才会创建对象。
    (2)ApplicationContext:BeanFactory的子接口,提供了更多更强大的功能,一般由开发人员使用。特点:加载配置文件时会把配置文件里的对象进行创建。
    (3)核心:Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的外部
    IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为Bean。
  • ApplicationContext两个常用的实现类:
    (1)FileSystemXmlApplicationContext:绝对路径,从盘符开始算起
    (2)ClassPathXmlApplicationContext:相对路径,从项目的src开始算起
  • IOC实现:依赖注入,即在容器中建立bean与bean之间的依赖关系的整个过程。

二、思路分析

  • IOC管理什么(bean对象)
  • 如何告知IOC去管理bean对象(通过配置文件)
  • 被管理的对象交给IOC容器,如何获取IOC容器?(接口)
  • IOC容器得到后,如何获取bean?(通过ApplicationContext接口的两个实现类的getBean方法获取bean实例创建对象)

三、IOC操作bean管理(基于xml,使用的是IDEA2022.3.3,maven仓库)

首先告诉大家本篇文章的所有使用的spring依赖版本:

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>6.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>6.0.9</version>
        </dependency>
        <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>6.0.9</version>
        </dependency>
    </dependencies>

1.xml实现bean管理

(1)创建对象

项目的resource资源文件夹创建spring的配置文件,然后添加如下代码:

<bean id="book" class="com.dragon.spring5.Book"></bean>
  • id:创建对象的名称
  • class:Book类的路径
  • 创建对象时默认是执行无参构造函数

(2)注入属性

创建对象后,对象内的属性还没有赋值等等,讲诉三种注入属性得到方式:

  • 第一种:set方法注入
    这种方法需要类的属性有对应的set方法,如下:
public class Book {
    private String bname;
    private String bauthor;
    public void setBname(String bname) {
        this.bname = bname;
    }
    public void setBauthor(String bauthor) {
        this.bauthor = bauthor;
    }
    public void testbook(){
        System.out.println(bname+":"+bauthor);
    }
}

然后在spring配置文件中通过property标签进行属性注入,如下:

<bean id="book" class="com.dragon.spring5.Book">
      <property name="bname" value="易筋经"></property>
            <property name="bauthor" value="达摩老祖"></property>
</bean>

然后测试:

<!--加载spring配置文件创建对象-->
  ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml");
  <!--反射-->
  Book book=context.getBean("book", Book.class);
  System.out.println(book);
  book.testbook();

  • 第二种:有参构造方法注入
    提供有参构造方法:
public class Book {
    private String bname;
    private String bauthor;
    public Book(String bname, String bauthor) {
        this.bname = bname;
        this.bauthor = bauthor;
    }
    public void testbook(){
        System.out.println(bname+":"+bauthor);
    }
}

然后在spring配置文件中,如下:

<bean id="book" class="com.dragon.spring5.Book">
          <constructor-arg name="bname" value="易筋经"></constructor-arg>
          <constructor-arg name="bauthor" value="达摩老祖"></constructor-arg>
</bean>

(3)p名称空间注入

set方法、测试的代码跟上诉一样,不再赘诉。

在spring配置文件中添加p名称空间,和配置代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       <!--添加p名称空间-->
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="book" class="com.dragon.spring5.Book" p:bname="九阴神功" p:bauthor="无名氏"></bean></beans>

(4)其他注入

1.注入的属性值是null或者有符号,如下:
<bean id="book" class="com.dragon.spring5.Book">
                <property name="bauthor">
                        <null/>
                </property>
                <property name="bname">
                        <value><![CDATA[<<读者>>]]></value>
                </property>
        </bean>
  • 有符号:用<![CDATA[带符号的属性值(包括符号)]]>
  • 空值:< null />

2.注入外部bean,如下:

spring配置文件:

  • ref:引用外部bean的id值
<bean id="userService" class="com.dragon.spring5.service.UserService">
        <property name="userDao" ref="userDaoImpl"></property>
    </bean>
    <bean id="userDaoImpl" class="com.dragon.spring5.dao.UserDaoImpl"></bean>

UserService、UserDao、UserDaoImpl、测试类代码:

package com.dragon.spring5.dao;
public interface UserDao {
    public void update();
}
=============================================================
package com.dragon.spring5.dao;
public class UserDaoImpl implements UserDao{
    @Override
    public void update() {
        System.out.println("dao update.......");
    }
}
=========================================================
package com.dragon.spring5.service;
import com.dragon.spring5.dao.UserDao;
public class UserService {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    public void add(){
        System.out.println("service add........");
        userDao.update();
    }
}
======================================================
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
UserService userService=context.getBean("userService", UserService.class);
userService.add();

3.内部bean注入

不通过ref属性,而是通过嵌套一个bean标签实现

spring配置文件:

<bean id="emp" class="com.dragon.spring5.bean.Emp">
            <property name="enanme" value="lucy"></property>
            <property name="gender" value="女"></property>
            <property name="dept">
                <bean id="dept" class="com.dragon.spring5.bean.Dept">
                    <property name="dname" value="保安部门"></property>
                </bean>
            </property>
        </bean>

Emp、Dept、测试类代码:

package com.dragon.spring5.bean;
public class Emp {
    private String enanme;
    private String gender;
    private Dept dept;
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public void setEnanme(String enanme) {
        this.enanme = enanme;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public void add(){
        System.out.println(enanme+"::"+gender+"::"+dept);
    }
}
===================================================================
package com.dragon.spring5.bean;
public class Dept {
    private String dname;
    public void setDname(String dname) {
        this.dname = dname;
    }
    @Override
    public String toString() {
        return "Dept{" +
                "dname='" + dname + '\'' +
                '}';
    }
}
==========================================================================
ApplicationContext context1=new ClassPathXmlApplicationContext("bean2.xml");
        Emp emp=context1.getBean("emp", Emp.class);
        emp.add();

4.级联赋值

写法一:也就是上面所说的外部bean,通过ref属性来获取外部bean

写法二:

emp类中有ename和dept两个属性,其中dept有dname属性,写法二需要emp提供dept属性的get方法。

<bean id="emp" class="com.dragon.spring5.bean.Emp">
                    <property name="enanme" value="john"></property>
                    <property name="gender" value="男"></property>
                    <!--写法一-->
                    <property name="dept" ref="dept"></property>
                    <!--写法二-->
                    <property name="dept.dname" value="技术部"></property>
                </bean>
                <bean id="dept" class="com.dragon.spring5.bean.Dept">
                    <property name="dname" value="财务部"></property>
                </bean>
5.注入集合

stu类:

package com.dragon.spring5.collectiontype;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Stu {
    private String[] courses;
    private List<String> list;
    private Map<String,String> maps;
    private Set<String> sets;
    private List<Course> courselist;
    public void setCourselist(List<Course> courselist) {
        this.courselist = courselist;
    }
    public void setSets(Set<String> sets) {
        this.sets = sets;
    }
    public void setCourses(String[] courses) {
        this.courses = courses;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }
    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
        System.out.println(courselist);
    }
}

Course类:

package com.dragon.spring5.collectiontype;
public class Course {
    private String cname;
    public void setCname(String cname) {
        this.cname = cname;
    }
    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + '\'' +
                '}';
    }
}

spring配置文件:

<bean id="stu" class="com.dragon.spring5.collectiontype.Stu">
        <property name="courses">
            <array>
                <value>java课程</value>
                <value>数据库课程</value>
            </array>
        </property>
        <property name="list">
            <list>
                <value>张三</value>
                <value>小三</value>
            </list>
        </property>
        <property name="maps">
            <map>
                <entry key="JAAVA" value="java"></entry>
                <entry key="PHP" value="php"></entry>
            </map>
        </property>
        <property name="sets">
            <set>
                <value>MySQL</value>
                <value>Redis</value>
            </set>
        </property>
        <!--外部bean注入-->
        <property name="courselist">
            <list>
                <ref bean="course1"></ref>
                <ref bean="course2"></ref>
            </list>
        </property>
</bean>
<bean id="course2" class="com.dragon.spring5.collectiontype.Course">
       <property name="cname" value="MyBatis框架"></property>
</bean>

测试:

ApplicationContext context=new ClassPathXmlApplicationContext("bean3.xml");
        Stu stu=context.getBean("stu", Stu.class);
        stu.test();

集合提取出来注入:

用util标签(注意util标签怎么引入):

Book类:

package com.dragon.spring5.collectiontype;
import java.util.List;
public class Book {
    private List<String> list;
    public void setList(List<String> list) {
        this.list = list;
    }
    public void test(){
        System.out.println(list);
    }
}
<?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:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                          http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
        <util:list id="booklist">
            <value>易筋经</value>
            <value>九阳神功</value>
            <value>九阴真经</value>
        </util:list>
        <bean id="book" class="com.dragon.spring5.collectiontype.Book" scope="prototype">
            <property name="list" ref="booklist"></property>
        </bean>
</beans>

(5)FactoryBean(工厂bean)

普通bean在配置文件中定义的bean类型就是返回类型。而工厂bean在配置文件定义的bean类型可以和返回类型不一样。

下面的MyBean类中实现FactoryBean接口,重写getObject,getObjectType方法。

这里把getObject重写成返回Course对象的方法。

package com.dragon.spring5.factorybean;
import com.dragon.spring5.collectiontype.Course;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<Course> {
    @Override
    public Course getObject() throws Exception {
        Course course=new Course();
        course.setCname("abc");
        return course;
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}

spring配置文件:

<bean id="mybean" class="com.dragon.spring5.factorybean.MyBean"></bean>

测试:

注意这里实例化对象不是MyBean类型,是上面getObject方法返回的对象类型。

ApplicationContext context=new ClassPathXmlApplicationContext("bean5.xml");
        Course course=context.getBean("mybean", Course.class);
        System.out.println(course);

2.bean的作用域

  • 在Spring中,默认情况下bean创建的是单实例对象:
ApplicationContext context1=new ClassPathXmlApplicationContext("bean4.xml");
        Book book1=context1.getBean("book", Book.class);
        Book book2=context1.getBean("book", Book.class);

可以看出地址一样

  • bean有个属性是scope,可以通过设置成singleton或prototype来决定其是单实例还是多实例(1)singleton:默认值,表示单实例对象。加载配置文件时就会创建单实例对象。
    (2)prototype:表示多实例对象。不是在加载配置文件时创建对象,在调用getBean方法时创建多实例对象。
<bean id="book" class="com.dragon.spring5.collectiontype.Book" scope="prototype">
            <property name="list" ref="booklist"></property>
</bean>

  • scope的值还可以是request、session(大家应该知道这两个值的作用域吧)

3.bean的生命周期

(1)通过构造器创建 bean 实例(无参数构造)

(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)

(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization

(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)

(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization

(6)bean 可以使用了(对象获取到了)

(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)

下面提供大家测试需要用的类,方便大家理解:

Orders类:

package com.dragon.spring5.bean;
public class Orders {
    private String oname;
    public Orders() {
        System.out.println("第一步 执行无参数构造创建bean实例");
    }
    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步 调用set方法设置属性值");
    }
    public void initMethod(){
        System.out.println("第三步 执行初始化方法");
    }
    public void destoryMethod(){
        System.out.println("第五步 bean销毁的方法");
    }
}

后置处理器:

package com.dragon.spring5.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return bean;
    }
}

测试:

package com.dragon.spring5.testDemo;
import com.dragon.spring5.bean.Orders;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test3 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean6.xml");
        Orders orders=context.getBean("orders", Orders.class);
        System.out.println("第四步 获取创建beam实例对象");
        System.out.println(orders);
        context.close();
    }
}

spring配置文件:

</bean>
<!--        后置处理器-->
        <bean id="myBeanPost" class="com.dragon.spring5.bean.MyBeanPost"></bean>

4.xml自动配置属性值

bean标签属性autowire两个常用值:

(1)byName:根据属性名称注入,注入值bean的id值和类属性名称一样

(2)byType:根据属性类型注入

spring配置文件:

(Emp类中有dept属性)

<bean id="emp" class="com.dragon.spring5.autowrite.Emp">
                <property name="dept" ref="dept"></property>
</bean>
<bean id="dept" class="com.dragon.spring5.autowrite.Dept"></bean>

正常情况下属性值需要用property标签注入。

而用autowire,可以自动注入

<bean id="emp" class="com.dragon.spring5.autowrite.Emp" autowire="byName"></bean>
        <bean id="dept" class="com.dragon.spring5.autowrite.Dept"></bean>

5.外部属性文件操作bean

这里用连接数据库举例:

在resource文件夹内jdbc属性文件(jdbc.properties)

pro.driverClass=com.mysql.jdbc.Driver
pro.url=jdbc:mysql://localhost:3306/?(这个根据自己数据库配置)
pro.username=root
pro.password=root

spring配置文件(注意context配置,这里使用的< context:property-placeholder/ >标签引入属性文件,其中classpath就是配置属性文件的全称):

<?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"
       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">
        <context:property-placeholder location="classpath:jdbc.properties"/>
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
                <property name="driverClassName" value="${pro.driverClass}"></property>
                <property name="url" value="${pro.url}"></property>
                <property name="username" value="${pro.username}"></property>
                <property name="password" value="${pro.password}"></property>
        </bean>
</beans>

四、注解实现bean管理

1.基于注解创建对象

spring提供四种创建对象的注解(下面四个注解说的一般使用在哪层是约定俗成的,其实效果都一样,都可以混用):

  • @Component
  • @Service:一般用于业务逻辑或Service层
  • @Controller:一般用于web层
  • @ Repository:一般用于Dao层
    步骤:
    (1)引入依赖(开头已告知所有maven依赖库)
    (2)开启组件扫描:扫描base-package包下所有有注解的类并为其创建对象
<context:component-scan base-package="com.dragon.spring5_1"></context:component-scan>

代表扫描com.dragon.spring5_1下的所有文件,找寻有注解的文件,然后创建实例。

(2)创建类并在类上创建对象注解

@Service(value = "userService")
public class UserService {
    public void add(){
        System.out.println("service add.......");
    }
}

测试:

ApplicationContext context=new ClassPathXmlApplicationContext("bean9.xml");
        UserService userService=context.getBean("userService",UserService.class);
        System.out.println(userService);
        userService.add();

2.组件扫描细节

还有两种用法:

设置不扫描的注解
      <context:component-scan base-package="com.dragon.spring5_1">
                <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/>
        </context:component-scan>
    设置扫描的注解
        <context:component-scan base-package="com.dragon.spring5_1" use-default-filters="false">
                <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
        </context:component-scan>

3.基于注解进行属性注入

  • @Autowired:根据属性类型自动装配
  • @Qualifier:根据属性名称自动装配,需要和@Autowired一起使用
    当遇到一个接口有很多实现类时,只通过@Autowire是无法完成自动装配的,所以需要再使用@Qualifier通过名称来锁定某个类
  • @Resource:可以根据类型注入,也可以根据名称注入(不常用)
  • @Value:注入属性值
    实例:
    UserDao、UserDaoImpl、UserService类:
package com.dragon.spring5_1.dao;
import org.springframework.stereotype.Repository;
public interface UserDao {
    public void add();
}
==================================================
package com.dragon.spring5_1.dao;
import org.springframework.stereotype.Repository;
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao{
    @Override
    public void add() {
        System.out.println("dao add......");
    }
}
=========================================================
package com.dragon.spring5_1.service;
import com.dragon.spring5_1.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service(value = "userService")
public class UserService {
    @Value(value = "abc")
    private String name;
    @Autowired
    @Qualifier(value ="userDaoImpl1")
    private UserDao userDao;
    public void add(){
        System.out.println("service add......."+name);
        userDao.add();
    }
}

spring配置文件:

<?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"
       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">
        <context:component-scan base-package="com.dragon.spring5_1"></context:component-scan>
</beans>

测试:

ApplicationContext context=new ClassPathXmlApplicationContext("bean9.xml");
        UserService userService=context.getBean("userService",UserService.class);
        System.out.println(userService);
        userService.add();

五、完全注解开发

上面讲诉后,完全注解开发应该是最简洁的。来个实例看一看。

这时要引入配置类来代替spring配置文件,来实现组件扫描不用xml配置,进而实现完全注解开发。

配置类:

package com.dragon.spring5_1.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration//配置类
@ComponentScan(basePackages = {"com.dragon.spring5_1"})//配置扫描的文件
public class SpringConfig {
}

测试(UserDao、UserDaoImpl、UserService还是上面基于注解属性注入例子的):

package com.dragon.spring5_1.testDemo;
import com.dragon.spring5_1.config.SpringConfig;
import com.dragon.spring5_1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class test2 {
    public static void main(String[] args) {
      //注意new的对象变了,变成了AnnotationConfigApplicationContext
        ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService=context.getBean("userService", UserService.class);
        System.out.println(userService);  
        userService.add();
    }
}

总结

以上就是Spring的IOC讲解。

相关文章
|
9天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
20天前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
2月前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
117 9
|
1月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
25 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
2月前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
38 4
|
21天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
49 0
|
2月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
105 3
|
29天前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
43 0
|
6天前
|
Kubernetes 监控 开发者
掌握容器化:Docker与Kubernetes的最佳实践
【10月更文挑战第26天】本文深入探讨了Docker和Kubernetes的最佳实践,涵盖Dockerfile优化、数据卷管理、网络配置、Pod设计、服务发现与负载均衡、声明式更新等内容。同时介绍了容器化现有应用、自动化部署、监控与日志等开发技巧,以及Docker Compose和Helm等实用工具。旨在帮助开发者提高开发效率和系统稳定性,构建现代、高效、可扩展的应用。