乐趣区

Spring-讲解二

1、Spring 容器加载的 3 种方式

public class ServiceTest {public static void main(String[] args) {
            //Spring 容器加载有 3 种方式

            // 第一种:ClassPathXmlApplicationContext ClassPath 类路径加载,指的就是 classes 路径
            // 第一种:最常用,spring 的配置文件路径以后就直接放在 src
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

            // 第二种方式:文件系统路径获得配置文件【绝对路径】//ApplicationContext context = new FileSystemXmlApplicationContext("C:\\Users\\Desktop\\IDEAWorkspace\\spring-01\\src\\com\\rookie\\beans.xml");

            // 第三种方式: 使用 BeanFactory(了解)
            //String path = "C:\\Users\\Desktop\\IDEAWorkspace\\spring-01\\src\\com\\rookie\\beans.xml";
            //BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
            //IUserService user = (IUserService) factory.getBean("userService");
            //user.add();

            IUserService user = (IUserService) context.getBean("userService");
            user.add();}
    }

Spring 内部创建对象的原理

a. 解析 xml 文件,获取类名,id, 属性等。

b. 通过反射,用类型创建对象。

c. 给创建的对象赋值。

2、BeanFactory 和 ApplicationContext 对比

BeanFactory 采取延迟加载,第一次 getBean 时才会初始化 Bean。

ApplicationContext 是即时加载,对 BeanFactory 扩展,提供了更多功能。

  • 案例演示 (在第一次的代码基础上)

    public class UserServiceImpl implements UserService {
    
        private String name;
    
        public void setName(String name) {this.name = name;}
    
        @Override
        public void add() {System.out.println("创建用户...." + name);
        }
    
        public UserServiceImpl(){System.out.println("UserServiceImpl() 调用了");
        }
    }
    public class ServiceTest {public static void main(String[] args) {
            //1. 加载 beans.xml 这个 spring 的配置文件, 内部就会创建对象
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        }
    }

    控制台打印日志:UserServiceImpl() 调用了

    public class ServiceTest {public static void main(String[] args) {
            String path = "C:\\Users\\Desktop\\IDEAWorkspace\\spring-01\\src\\com\\rookie\\beans.xml";
    BeanFactory factory = new XmlBeanFactory(new FileSystemResource(path));
            
            // 要使调用空参构造可以放开这段代码即可
            // IUserService user = (IUserService) factory.getBean("userService");
        }
    }

    控制台没有打印日志,说明空参构造没有被调用。

    放开上面注释的代码,即可调用空参构造,控制台打印日志:UserServiceImpl() 调用了。

2、Spring 容器装配 bean 的 3 种方式

所谓的装配 bean 就是在 xml 写一个 bean 标签。

<?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 的三种方式,所谓的装配 bean 就是在 xml 写一个 bean 标签 -->
    
    <!-- 第一种方式: new 实现类 -->
    <bean id="userService1" class="com.example.demo.service.impl.UserServiceImpl">
        <property name="name" value="zhangsan"></property>
    </bean>

    <!-- 第二种方式:通过静态工厂方法 -->
    <bean id="userService2" class="com.example.demo.service.UserServiceFactory" factory-method="createUserService"/>

    <!-- 第三种方式:通过实例工厂方法 -->
    <bean id="factory2" class="com.example.demo.service.UserServiceFactory2"/>
    <bean id="userService3" factory-bean="factory2" factory-method="createUserService"/>
</beans>

测试上面哪种 bean 装配方式,需要注释掉其他 bean 装配方式。

第一种上次已经讲过,现在只讲第二、三种案例。

public class UserServiceFactory {public static UserService createUserService() {return new UserServiceImpl();
    }
}

=========================================================================================
public class UserServiceFactory2 {public UserService createUserService() {return new UserServiceImpl();
    }
}

执行测试函数

public class ServiceTest {public static void main(String[] args) {

        //new 对象
        ApplicationContext context1 = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService1 = (UserService) context1.getBean("userService1");
        userService1.add();


        // 静态工厂
        ApplicationContext context2 = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService2 = (UserService) context2.getBean("userService2");
        userService2.add();


        // 实例工厂
        ApplicationContext context3 = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService3 = (UserService) context3.getBean("userService3");
        userService3.add();}
}

感兴趣的可以自己看执行结果。三种结果都证明 bean 被 Spring 容器管理实例化了。

3、bean 的作用域 (掌握 singleton、prototype)

类别 说明
singleton 在 Spring IoC 容器中仅存在一个 Bean 实例,Bean 以单例方式存在,默认值
prototype 每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 getBean() 时,相当于执行 new XxxBean()
request 每次 HTTP 请求都会创建一个新的 Bean,该作用域仅适用于 WebApplicationContext 环境
session 同一个 HTTP Session 共享一个 Bean,不同 Session 使用不同 Bean,仅适用于 WebApplicationContext 环境
globalSession 一般用于 Portlet 应用环境,该作用域仅适用于 WebApplicationContext 环境

案例代码演示

bean.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="userService1" class="com.example.demo.service.impl.UserServiceImpl" scope="prototype">
    </bean>
</beans>
public class ServiceTest {public static void main(String[] args) {ApplicationContext context1 = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService1 = (UserService) context1.getBean("userService1");
        UserService userService2 = (UserService) context1.getBean("userService1");
        System.out.println(userService1);
        System.out.println(userService2);
    }
}

控制台信息如下:

com.example.demo.service.impl.UserServiceImpl@2a556333
com.example.demo.service.impl.UserServiceImpl@7d70d1b1

如果去掉 bean.xml 文件的 scope=”prototype”,打印信息如下:

com.example.demo.service.impl.UserServiceImpl@7a187f14
com.example.demo.service.impl.UserServiceImpl@7a187f14

所以 Spring IoC 容器 Bean 以单例方式默认存在!!配置的话根据自己需要配置单例或者多例

退出移动版