springIOC原理的最详尽解读

1.spring的核心俩大类 IOC 和AOP(任何一个spring的项目离不开ioc)
要了解Ioc入手点:

1. 概念:
控制反转(Inversion of Control)------>它是一种设计思想。

2. 目的:
降低程序之间的耦合度。(而不是消除)
剖析概念:控制的是什么?反转的又是什么呢。

我们举个例子:以往:我们一个类(Student)中需要调用另一个类(Couse)中的(study)方法。
1

> .   在Student类中  ,实例化一个couse对象再调用study方法
>       public class Student{
>          Couse cs=new Couse();
>          cs.study();
>      }

这样对Student类来说是:我需要couse类中的方法,我就自己创建它。这就是(主动控制)。

这样的弊端: 就是student类和couse类之间的耦合度太高。为了降低耦合程度,我们引入了反转控制的概念,即spring的IOC

IOC:将自主创建对象的权利,交给spring来管理。以后我们需要什么样的对象,我们自己不创建,而是像spring容器要。这样就把我们主动控制对象,以及对象的生命周期,反转给了spring,交由它来负责。这就是控制反转,也叫反转控制。
那么概念搞清楚后,我们就要了解spring是如何替我们管理bean对象的呢?

首先了解spring创建bean对象的三种方式:
  • 第一种创建bean的方式

    使用默认构造函数创建,配以id和class属性之后,没有别的标签,就是默认构造函数创建此时如果类中没有默认构造函数,对象无法被创建。

   <bean id="UserDao" class="com.zrj.dao.impl.UserDaoImpl"></bean>
  
  • 第二种创建bean的方式

    使用普通工厂类中的方法创建对象

<bean id="factoryMy" class="com.zrj.factory.factoryMy"></bean>
<bean id="UserService" factory-bean="factoryMy" factory-method="getUserServiceImpl"></bean>
  • 第三种创建bean的方式

    使用普通工厂类中的静态方法创建对象

   <bean id="staticfactoryMy" class="com.zrj.factory.StaticfactoryMy" factory-method="getUserServiceImpl"></bean>

再来了解bean的作用范围
默认是单例的(对象只会被创建一次)
bean中有个属性:

scope

作用:指定bean的作用范围
取值:singleton 单例(默认值)
prototype 多例
request 作用于web应用的请求范围
session 作用于web应用的会话范围
global-session 作用于集群环境的会话范围(全局会话),当不是集群环境,它就是session

接下来再了解bean的生命周期:(这里分单例跟多例的情况)

单例的bean

顾名思义就是:
出生:容器被初始化时对象被创建
活着:容器在对象在
死亡:容器销毁对象消亡
总结:生命周期跟容器相同

多例的bean

出生:当我们什么时候用,spring再为我们创建
活着:对象只要在使用过程中,就一直活在
死亡:当对象长时间不用时,或者没有其他对象对他的引用时,java的垃圾 回收机制会帮我们回收处理。

那么spring创建bean的过程就是依赖注入的过程:

注入的3种方式:
  • 构造器注入
    bean 标签内部使用一个标签 constroctor-arg

  • setter注入
    bean 标签内部使用一个标签 property

  • 接口的注入

至此IOC的体现已经结束,我们怎么去获取容器中的bean对象呢?
1.首先我们需要获得容器

这里用一个接口叫 ApplicationContext。它下面有3个常用的实现类。

  • ClassPathXmlApplicationContext
    注意:它可以加载类路径下的配置文件(xxx.xml),要求配置文件必须在类路径下。不在的,创建不了.
 ApplicationContext ac = new  ClassPathXmlApplicationContext("xxx.xml");
  • FileSystemXmlApplicationContext
    它可以加载磁盘任意路径下的配置文件(必须有访问权限)
  ApplicationContext ac = new  FileSystemXmlApplicationContext("D:\\config\\xxx.xml");
  • AnnotationConfigApplicationContext
    它是用于读取注解创建容器的

核心容器的俩个接口引发的问题:

  • ApplicationContext 单例对象适用 :创建对象采取的策略是:立即加载的方式,即 一读完配置文件就创建文件中配置的对象
  • BeanFactory 多例对象适用 :它在构建容器时,采取的策略是:延迟加载(懒加载),什么时候需要这个对象,我再创建。

**

接下来我们说说通过注解的方式来创建对象,并存入spring容器。

前提是需要在xml中配置spring容器要扫描的包

比如配置到com.zrj的包路径下,表示该路径下的所有注解都会被spring容器扫描。

  <context:component-scan base-package="com.zrj"></context:component-scan>
  • 第一种注解,用来创建bean对象的

@Component 将当前类对象存入spring容器中

下面的这3个注解的作用和Component一模一样,是spring框架为我们提供明确的3层使用的注解,使3层对象跟家清晰

@Controller
@Service
@Repostory

  • 第二种用于注入数据的

@Autowired 自动按照类型注入,只要容器中有一个唯一的bean’对象类型,就可以注入成功

@Resource 根据bean的id注入

注意:以上的2个注解只能注入bean类型,不能注入String类型和基本类型,集合类型只能通过xml方式注入

@Value 用于注入基本类型和String类型的数据 ,属性value 用于指定数据的值,也可以使用spring的el表达式指定,${}

上面讲spring中的bean对象的配置都通过注解来实现了,那么能不能去除配置文件呢?
首先需要将扫描的包的配置去除,就可以通过下面这个注解实现

@ComponentScan(basePackages = “com.zrj”)

那么接下来还有一些配置文件中的约束等等信息怎么办呢?
可以通过自定义配置类来完成。

在自定义类上加入@Configuration注解

该类就相当于配置 文件的xml
@Configuration
@ComponentScan(basePackages = "com.zrj")
public class XmlConfig {
 // <bean id="IUserService" class="com.zrj.service.impl.UserServiceImpl"></bean>
    
    @Bean 作用:将当前的方法的返回值作为bean对象,存入spring的ioc容器中
    public IUserService getUserService(){
        return  new UserServiceImpl();
    }
}

接下来我们需要将该配置类加载进我们的程序中,web应用可以在web.xml中配置。
还有就是我们前面讲到了

AnnotationConfigApplicationContext 他是用来加载注解配置的

AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext();
         ac.register(configXml.class);
         ac.refresh();

然后就可以通过ac对象调用配置类中的bean对象了。

  AccountService accountService = ac.getBean("accountService", AccountService.class);

猜你喜欢

转载自blog.csdn.net/weixin_43028416/article/details/105855000