3.IoC 使用
3.1 IoC的工作原理
- 我们在程序设计时,所秉承的思想一般都是在不影响系统功能的前提下,最大限度的降低耦合度。
IoC 底层通过工厂模式、Java 的反射机制、XML 解析等技术,将代码的耦合度降低到最低限度,其主要步骤如下。
- 在配置文件(例如 Bean.xml)中,对各个对象以及它们之间的依赖关系进行配置;
- 我们可以把 IoC 容器当做一个工厂,这个工厂的产品就是 Spring Bean;
- 容器启动时会加载并解析这些配置文件,得到对象的基本信息以及它们之间的依赖关系;
- IoC 利用 Java 的反射机制,根据类名生成相应的对象(即 Spring Bean),并根据依赖关系将这个对象注入到依赖它的对象中。
- 由于对象的基本信息、对象之间的依赖关系都是在配置文件中定义的,并没有在代码中紧密耦合,因此即使对象发生改变,我们也只需要在配置文件中进行修改即可,而无须对 Java 代码进行修改,这就是 Spring IoC 实现解耦的原理。
3.2 IoC 容器的两种实现
-
IoC 思想基于 IoC 容器实现的,IoC 容器底层其实就是一个 Bean 工厂。Spring 框架为我们提供了两种不同类型 IoC 容器,它们分别是 BeanFactory 和 ApplicationContext。
-
BeanFactory容器
BeanFactory 是 IoC 容器的基本实现,也是 Spring 提供的最简单的 IoC 容器,它提供了 IoC 容器最基本的功能(生产、管理和获取Bean),由 org.springframework.beans.factory.BeanFactory 接口定义。
注意:BeanFactory 是 Spring 内部使用接口,通常情况下不提供给开发人员使用。
BeanFactory 采用懒加载(lazy-load)机制,容器在加载配置文件时并不会立刻创建 Java 对象,只有程序中获取(使用)这个对对象时才会创建。
Spring创建Bean有三种基础方式,
无参构造,静态方法,实例化方法
原文链接:https://blog.csdn.net/u010689440/article/details/108423829<!--方式一:无参构造方式(推荐) 在默认情况下,它会通过反射调用无参构造函数来创建对象。如果类中没有无参构造函数,将创建 失败。 --> <!--<bean id="beanname" class="beanClass"/>--> <!--另外两种方式,是为了将我们自己new的bean加入ioc容器管理--> <!--方式二:静态方法--> <!--<bean id="beanname" class="beanClass" factory-method="beanClassStaticMethod"/>--> <!--方式三:实例化方法 此种方式和上面静态方法创建其实类似,区别是用于获取对象的方法不再是static修饰的了,而是 类中的一 个普通方法。 -->
FactoryBean: Spring管理的Bean有两种,一种是普通Bean,一种是工厂Bean(FactoryBean),FactoryBean可以自定义创建一个复杂Bean实例交给IOC容器管理;Spring框架的一些组件和其他框架整合Spring时会使用FactoryBean来实例化复杂Bean;
<bean id="createFactory" class="com.wjy.factory.CreateBeanFactory"/> <bean id="connectionUtils" factory-bean="createFactory" factory-method="getConnectionUtils"/>
静态方法,实例化方法
可以实现自定义创建复杂Bean,但配置复杂,而FactoryBean
配置和无参构造
方式一样简单对于使用全注解开发项目,只能使用
FactoryBean
来自定义复杂Bean;后置处理器(重要AOP的实现)
- Spring提供了两种后处理bean的扩展接口,分别为BeanPostProcessor和BeanFactoryPostProcessor,两者在使用上是有所区别的。
- BeanPostProcessor: 用来处理BeanFactory实例化的Bean;(代理模式思想)
BeanFactoryPostProcessor: 用来拦截处理BeanFactory解析完配置后的ConfigurableListableBeanFactory其中包含所有配置的Bean的定义对象BeanDefinition,可以对他进一步处理;
BeanPostProcessor该接口提供了两个方法,分别在Bean的初始化方法前和初始化方法后执行,具体这个初始化方法指的是 什么方法,类似我们在定义bean时,定义了init-method所指定的方法;
实现:定义一个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进行处理。如果要对 具体的某个bean处理,可以通过方法参数判断,两个类型参数分别为Object和String,第一个参数是每 个bean的实例,第二个参数是每个bean的name或者id属性的值。所以我们可以通过第二个参数,来判 断我们将要处理的具体的bean。
// 拦截实例化之后的对象(实例化了并且属性注入了)
@Component
public class MyBean implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(“MyBeanPostProcessor before init-method方法拦截处理”);
return bean;
}@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("MyBeanPostProcessor afterinit-method方法拦截处理"); return bean; }
}
注意:处理是发生在Spring容器的实例化和依赖注入之后。
spring对Bean的声明周期
- ApplicationContext容器
ApplicationContext 是 BeanFactory 接口的子接口,是对 BeanFactory 的扩展。ApplicationContext 在 BeanFactory 的基础上增加了许多企业级的功能,例如 AOP(面向切面编程)、国际化、事务支持等。
ApplicationContext: 容器的默认行为是在启动服务器时将所有 singleton bean 提前进行实例化。
这样如果项目比较大,Spring管理的类比较多,会造成每次启动项目耗时比较长的问题,这里我们就需要延迟加载特性;
延迟加载:指程序启动时不会默认实例化类,只有在被管理的bean使用的时候才会实例化;
- id前添加&获取工厂* CompanyFactoryBean Factory = context.getBean(“&companyBean”);
- 拓展:懒加载
- 开启延迟加载一定程度提高容器启动和运转性能
- 对于不常使用的 Bean 设置延迟加载,这样偶尔使用的时候再加载,不必要从一开始该 Bean 就占用资源。
- 配置方式:
xml方式:
- 全局配置
- 指定bean配置 在bean中加属性lazy-init=“true”
注解方式:
- 全局配置:Spring配置类上添加
@Lazy
注解,即可开启全局懒加载- 在指定类上添加
@Lazy
注解,即可开启懒加载
- 对实体的的无参构造方法加输出
@Test
public void TestDemo02(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Beans.xml");
/*Hello hello = applicationContext.getBean("hello", Hello.class);
System.out.println(hello.getMessage());*/
}
- application容器在加载配置文件,容器中管理的对象就已经初始化了,除非在xml配置中加上 lazy-init=“true”,这样懒加载就能在使用的时候才加载,内存中只有一份实例,默认是单例模式。
- beanfactory容器是懒加载即调用getBean()创建对象。
- 容器加载配置文件时实例化bean默认是单例模式,这个 Bean 实例将存储在高速缓存中,所有对于这个 Bean 的请求和引用,只要 id 与这个 Bean 定义相匹配,都会返回这个缓存中的对象实例。
3.3 IOC创建对象的方式
-
控制反转核心思想就是由 Spring 负责对象的创建。
-
使用无参构造创建实例,将property属性使用setter注入(值注入)—-默认
-
另一种是使用构造器创建对象的时候是使用有参构造创建实例并进行属性注入
-
- 有参构造形式一:通过下标赋值
<bean id="hello" class="com.zk.pojo.Hello"> <constructor-arg index="0" value="位置"/> </bean>
- 参构造形式二:通过参数type类型(两个同类型参数会默认按照顺序给你参数赋值)—不推荐
<bean id="hello" class="com.zk.pojo.Hello"> <constructor-arg type="java.lang.String" value="位置信息"/> <constructor-arg type="java.lang.String" value="网络"/> </bean>
- 有参构造形式三:通过参数名来赋值
<bean id="hello" class="com.zk.pojo.Hello">
<constructor-arg name="message" value="信息"/>
</bean>
本专栏下一篇:spring配置
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123913.html