spring源码学习(一)spring复习之IOC

Spring的核心思想

image

IOC

1、BeanFactory

示例
    public static void main(String[] args) {
        //bean工厂
        DefaultListableBeanFactory beanFactory =new DefaultListableBeanFactory();
        //xml读取
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //读取xml
        reader.loadBeanDefinitions("beans.xml");
        UserService userService =(UserService) beanFactory.getBean("userService");
        System.out.println(userService);
    }

xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.cdc.service.UserServiceImpl">
    </bean>
</beans>
1.1、set注入

xml文件

    <bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
        <property name="abcDao" ref="userDao"></property>
    </bean>
    <bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
    </bean>

UserDaoImpl.java

public class UserDaoImpl implements UserDao {
}

UserServiceImpl.java

public class UserServiceImpl implements UserService {
    public void setAbcDao(UserDao userDao){
        System.out.println("set注入啦:"+userDao);
    }
}

测试文件

public class TestSpringIOC {

    public static void main(String[] args) {
        //bean工厂
        DefaultListableBeanFactory beanFactory =new DefaultListableBeanFactory();
        //xml读取
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //读取xml
        reader.loadBeanDefinitions("beans.xml");
        UserService userService =(UserService) beanFactory.getBean("userService");
        System.out.println(userService);
    }
}

输出:

set注入啦:com.cdc.dao.impl.UserDaoImpl@56de5251
com.cdc.service.impl.UserServiceImpl@419c5f1a
  • 注意set方法注入关键,set方法名,后面第一个字母转小写,要跟<property name="abcDao" ,里面的name对应好

2、ApplicationContext (一)

    <bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
        <property name="abcDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
    </bean>
public class TestApplicationContext {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService =(UserService) applicationContext.getBean("userService");
        System.out.println(userService);
    }
}
通配符方式加载多个配置文件

image

3、ApplicationContext与BeanFactory关系

image

image

  • ApplicationContext内部有个BeanFactory接口的实现类DefaultListableBeanFactory

image

  • DefaultListableBeanFactory内部有个beanDefinitionMap,是bean的定义信息集合,现在有2个bean

image

  • DefaultListableBeanFactory内部有个singletonObjects,是单例池,里面放的是具体的bean

spring web的ApplicationContext

后面再翻看
image

4、ApplicationContext (二)

4.1、别名

    <bean class="com.cdc.service.impl.UserServiceImpl">
        <property name="abcDao" ref="userDao"></property>
    </bean>

image
image

  • 之前配置的id即bean的别名,getBean("userService"),就是通过别名获取的。
  • 没有配id,默认别名就是类的全限定名,通过这样的方式获取bean,
    UserService userService =(UserService) applicationContext.getBean("com.cdc.service.impl.UserServiceImpl");

4.1.1取多个别名

    <bean id="userService" name="aaa,ccc,bbb" class="com.cdc.service.impl.UserServiceImpl">
        <property name="abcDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
    </bean>
public class TestApplicationContext {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService =(UserService) applicationContext.getBean("userService");
        UserService userService2 =(UserService) applicationContext.getBean("aaa");
        UserService userService3 =(UserService) applicationContext.getBean("bbb");
        UserService userService4 =(UserService) applicationContext.getBean("ccc");
        System.out.println(userService);
        System.out.println(userService2);
        System.out.println(userService3);
        System.out.println(userService4);
    }
}

默认别名是id
image
image
BeanFactory内部有个aliasMap,可以进行别名的映射
image

4.1.2 没有配置id时,默认别名取第一个 aaa

    <bean name="aaa,ccc,bbb" class="com.cdc.service.impl.UserServiceImpl">
        <property name="abcDao" ref="userDao"></property>
    </bean>

4.2 scope 作用范围

4.2.1默认单例

    <bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
    </bean>

4.2.2可原型模式

    <bean id="userService" class="com.cdc.service.impl.UserServiceImpl" scope="prototype">
    </bean>
public class TestApplicationContext {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService =(UserService) applicationContext.getBean("userService");
        UserService userService2 =(UserService) applicationContext.getBean("userService");
        UserService userService3 =(UserService) applicationContext.getBean("userService");
        System.out.println(userService);
        System.out.println(userService2);
        System.out.println(userService3);
    }
}

输出:

com.cdc.service.impl.UserServiceImpl@43195e57
com.cdc.service.impl.UserServiceImpl@333291e3
com.cdc.service.impl.UserServiceImpl@479d31f3

4.3延迟加载

    <bean id="userService" class="com.cdc.service.impl.UserServiceImpl" lazy-init="true">
    </bean>
创建容器后,单例池singletonObjects没有bean,执行了getBean方法时,才创建bean放进单例池。
        //1.创建容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.从容器中取bean
        UserService userService =(UserService) applicationContext.getBean("userService");
        System.out.println(userService);
  • 注意,创建容器后,beanDefinitionMap是有userService的bean定义信息的

4.4 读取多个xml配置文件,以及根据类型获取bean

image

4.5 spring是默认调用bean的无参构造方法实例化的

public class UserServiceImpl implements UserService {

    public UserServiceImpl(){
        System.out.println("实例化,调用无参构造");
    }

    private UserDao userDao;

    //set注入,set后面的字符串
    public void setAbcDao(UserDao userDao){
        this.userDao=userDao;
        System.out.println("set注入啦:"+userDao);
    }

}
public class TestApplicationContext {
    public static void main(String[] args) {
        //1.创建容器,可以根据多个配置文件创建
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.从容器中取bean
        UserService userService =(UserService) applicationContext.getBean("userService");
        System.out.println(userService);
    }
}

输出:

实例化,调用无参构造
com.cdc.service.impl.UserServiceImpl@123ef382

4.6构造注入

public class UserServiceImpl implements UserService {

    public UserServiceImpl(){
        System.out.println("实例化,调用无参构造");
    }

    public UserServiceImpl(String name,int num){
        System.out.println("实例化,调用有参构造"+name+num);
    }

    private UserDao userDao;

    //set注入,set后面的字符串
    public void setAbcDao(UserDao userDao){
        this.userDao=userDao;
        System.out.println("set注入啦:"+userDao);
    }

}
    <bean id="userService" class="com.cdc.service.impl.UserServiceImpl">
        <constructor-arg name="name" value="nihao"></constructor-arg>
        <constructor-arg name="num" value="60"></constructor-arg>
        <property name="AbcDao" ref="userDao"></property>
    </bean>

    <bean id="userDao" class="com.cdc.dao.impl.UserDaoImpl">
    </bean>

输出:

实例化,调用有参构造nihao60
set注入啦:com.cdc.dao.impl.UserDaoImpl@22555ebf
com.cdc.service.impl.UserServiceImpl@4d1c00d0

4.7 静态方法工厂加载Bean

public class BookFactory {

    public static BookDTO bookDTOBuild(String carName,int num){
        //使用静态方法注入
        //可以在此处写点别的代码
        return new BookDTO();
    }
}

springBook.xml

    <bean id="book" class="com.cdc.factory.BookFactory" factory-method="bookDTOBuild">
            <!--构造参数注入-->
            <constructor-arg name="carName" value="benz"></constructor-arg>
            <constructor-arg name="num" value="60"></constructor-arg>
    </bean>
public class TestApplicationContextFactory {
    public static void main(String[] args) {
        //1.创建容器,可以根据多个配置文件创建
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springBook.xml");
        //2.从容器中取bean
        BookDTO bookDTO =(BookDTO) applicationContext.getBean("book");
        System.out.println(bookDTO);
    }
}

4.8 实例方法工厂加载Bean

public class MyBeanFactory2 {
    public UserDao userDao(String carName,int num){
        return new UserDaoImpl();
    }
}
    <bean id="myBeanFactory2" class="com.cdc.factory.MyBeanFactory2"></bean>

    <bean id="userDao2" factory-bean="myBeanFactory2" factory-method="userDao">
             <!--构造参数注入-->
            <constructor-arg name="carName" value="benz"></constructor-arg>
            <constructor-arg name="num" value="60"></constructor-arg>
    </bean>
        UserDao userDao2 =(UserDao) applicationContext.getBean("userDao2");
        System.out.println(userDao2);
  • 配置实例化工厂类,实例化工厂类来产生bean
与静态方法工厂的区别

实例化工厂类也要进单例池
image

4.9FactoryBean实现延迟加载

public class MyBeanFactory3 implements FactoryBean<UserDao> {

    @Override
    public UserDao getObject() throws Exception {
        return new UserDaoImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return UserDao.class;
    }
}
<bean id="userDao3" class="com.cdc.factory.MyBeanFactory3"></bean>
4.9.1 执行了ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");单例内不会有userDao3的实例,只会有一个实现FactoryBean接口的实例

image

4.9.2 执行了UserDao userDao3 =(UserDao) applicationContext.getBean("userDao3");才会在缓冲池内有个userDao3的实例,下次getBean,也是从该缓冲池取

image

4.10属性注入集合、数据

4.10.1List<String>集合

image
image

4.10.2.1对象集合,集合内代表三个不同的UserDaoImpl实例

image
image

4.10.2.2对象集合,也可配置在外面

image

set String集合

image
image

set 对象集合

image
image

map 集合

image
image

properties对象

image
image

4.11 自动注入

image
1.通过名字自动注入

public class UserServiceImpl implements UserService {
    public void setUserDao3(UserDao userDao){
        System.out.println("set注入userDao:"+userDao);
    }
}
    <beans>
        <bean id="UserService" class="com.cdc.service.impl.UserServiceImpl" autowire="byName"></bean>
        <bean id="userDao3" class="com.cdc.dao.impl.UserDaoImpl"></bean>
    </beans>
  • set方法后面的名字一定要和bean的id(name)一致
    2.通过类型自动注入
    <beans>
        <bean id="UserService" class="com.cdc.service.impl.UserServiceImpl" autowire="byType"></bean>
        <bean id="userDao3" class="com.cdc.dao.impl.UserDaoImpl"></bean>
    </beans>

4.12 命名空间

4.12.1 spring默认的命名空间

image

4.12.2 引入其他的命名空间

image

4.12.2.1 接着就可以使用其他的标签了

image

4.12.3

4.12.3.1

image

4.12.3.2

image

4.12.3.3

image

4.12.4

4.12.4.1

image

4.12.4.2

image

4.12.4.3

image

4.13 profile环境标签

image

指定test,可以获取userDao1

image
image

不指定环境,只能获取到userService和userDao

image

  • 指定dev,可以获取userService1、userService和userDao
  • 指定test,可以获取userDao1、userService和userDao
  • 上图红色框框的相当于公共部分

4.13 import标签

image

4.13.1 示例

applicationContext.xml文件
image
image
image
只读取applicationContext.xml文件,就可以读取到applicationContext-order.xml和applicationContext-user.xml配置的bean
image

4.14 alias别名标签

image
image

4.15 使用容器注册bean

posted @ 2026-03-05 09:16  dvdhellohaha  阅读(15)  评论(0)    收藏  举报