Spring IoC进阶
- IOC之BeanFactory与ApplicationContext区别
- 启动 IoC 容器的方式
- 实例化Bean的三种⽅式
- 使用无参构造方法实例化
- 工厂静态方法实例化
- 工厂实例方法实例化
- Spring IOC之延迟加载(lazy-Init )
- Bean的延迟加载(延迟创建)
- 应用场景
IOC之BeanFactory与ApplicationContext区别
BeanFactory是Spring框架中IoC容器的顶层接⼝,它只是⽤来定义⼀些基础功能,定义⼀些基础规范,⽽ApplicationContext是它的⼀个⼦接⼝,所以ApplicationContext是具备BeanFactory提供的全部功能的。
通常,我们称BeanFactory为SpringIOC的基础容器, ApplicationContext是容器的⾼级接⼝,⽐BeanFactory要拥有更多的功能,⽐如说国际化⽀持和资源访问(xml, java配置类)等等 。
启动 IoC 容器的方式
- Java环境下启动IoC容器
- ClassPathXmlApplicationContext:从类的根路径下加载配置⽂件(推荐使⽤)
- FileSystemXmlApplicationContext:从磁盘路径上加载配置⽂件
- AnnotationConfigApplicationContext:纯注解模式下启动Spring容器
- Web环境下启动IoC容器
- 从xml启动容器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app><display-name>Archetype Created Web Application</display-name><!--配置Spring ioc容器的配置⽂件--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><!--使⽤监听器启动Spring的IOC容器--><listener><listenerclass>org.springframework.web.context.ContextLoaderListener</listenerclass></listener>
</web-app>
- 从配置类启动容器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app><display-name>Archetype Created Web Application</display-name><!--告诉ContextloaderListener知道我们使⽤注解的⽅式启动ioc容器--><context-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></context-param><!--配置启动类的全限定类名--><context-param><param-name>contextConfigLocation</param-name><param-value>com.zjq.spring.SpringConfig</param-value></context-param><!--使⽤监听器启动Spring的IOC容器--><listener><listenerclass>org.springframework.web.context.ContextLoaderListener</listenerclass></listener>
</web-app>
实例化Bean的三种⽅式
使用无参构造方法实例化
在默认情况下,它会通过反射调⽤⽆参构造函数来创建对象。如果bean中没有默认无参构造函数,将会创建失败
<bean id="userDao" class="com.zjq.dao.impl.UserDaoImpl"/>
工厂静态方法实例化
工厂的静态方法返回Bean实例
在实际开发中,我们使⽤的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创建的过程 中会做很多额外的操作。此时会提供⼀个创建对象的⽅法,恰好这个⽅法是static修饰的⽅法,即是此种情况。
例如,我们在做Jdbc操作时,会⽤到java.sql.Connection接⼝的实现类,如果是mysql数据库,那么⽤的就 是JDBC4Connection,但是我们不会去写JDBC4Connection connection = new JDBC4Connection() ,因为我们要注册驱动,还要提供URL和凭证信息,⽤DriverManager.getConnection ⽅法来获取连接。
public class StaticFactoryBean {public static UserDao createUserDao(){ return new UserDaoImpl();}
}
<bean id="userDao" class="com.zjq.factory.StaticFactoryBean" factory-method="createUserDao" />
工厂实例方法实例化
工厂的非静态方法返回Bean实例
此种⽅式和上⾯静态⽅法创建其实类似,区别是⽤于获取对象的⽅法不再是static修饰的了,⽽是类中的⼀ 个普通⽅法。此种⽅式⽐静态⽅法创建的使⽤⼏率要⾼⼀些。
在早期开发的项⽬中,⼯⼚类中的⽅法有可能是静态的,也有可能是⾮静态⽅法,当是⾮静态⽅法时,即可采⽤下⾯的配置⽅式
public class DynamicFactoryBean { public UserDao createUserDao(){ return new UserDaoImpl(); }
}
<bean id="factoryBean" class="com.zjq.factory.DynamicFactoryBean"/>
<bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>
Spring IOC之延迟加载(lazy-Init )
Bean的延迟加载(延迟创建)
ApplicationContext 容器的默认⾏为是在启动服务器时将所有 singleton bean 提前进⾏实例化。提前实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的singleton bean。
比如:
<bean id="testBean" class="com.zjq.TestBean" />
# 该bean默认的设置为:
<bean id="testBean" calss="com.zjq.TestBean" lazy-init="false" />
lazy-init=“false”,⽴即加载,表示在spring启动时,⽴刻进⾏实例化。
如果不想让⼀个singleton bean 在 ApplicationContext实现初始化时被提前实例化,那么可以将bean设置为延迟实例化。
<bean id="testBean" calss="com.zjq.TestBean" lazy-init="false" />
设置 lazy-init 为 true 的 bean 将不会在 ApplicationContext 启动时提前被实例化,⽽是第⼀次向容器通过getBean 索取 bean 时实例化的。
如果⼀个设置了⽴即加载的 bean1,引⽤了⼀个延迟加载的 bean2 ,那么 bean1 在容器启动时被实例化,⽽ bean2 由于被 bean1 引⽤,所以也被实例化,这种情况也符合延时加载的 bean 在第⼀次调⽤时才被实例化的规则。
也可以在容器层次中通过在 元素上使⽤ “default-lazy-init” 属性来控制延时初始化。如下⾯配置:
<beans default-lazy-init="true"><!-- no beans will be eagerly pre-instantiated... -->
</beans>
如果⼀个 bean 的 scope 属性为 scope=“pototype” 时,即使设置了 lazy-init=“false”,容器启动时也不
会实例化bean,⽽是调⽤ getBean ⽅法实例化的。
应用场景
- 开启延迟加载⼀定程度提⾼容器启动和运转性能。
- 对于不常使⽤的 Bean 设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean 就占⽤资源。
相关文章:Spring核心思想之IOC和AOP
本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。
主页:共饮一杯无的博客汇总👨💻保持热爱,奔赴下一场山海。🏃🏃🏃