初识Spring——Spring核心容器

释放双眼,带上耳机,听听看~!

一. IOC和DI基础

   IOC-Inversion of Control,译为控制反转,是一种遵循依赖倒置原则的代码设计思想。

  所谓依赖倒置,就是把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现前面的“牵一发动全身”的情况。
  而控制反转就是把传统程序中需要实现对象的创建、代码的依赖,反转给一个专门的\"第三方\"即容器来实现,即将创建和查找依赖对象的控制权交给容器,由容器将对象进行组合注入,实现对象与对象的松耦合,便于功能的复用,使程序的体系结构更灵活。

  

  DI-Dependency Injection,译为依赖注入,实际上是对Ioc的另一种称呼。2004年,大师级人物Martin Fowler为“控制反转”取了一个更合适的名字“依赖注入”。给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。

  理解IOC和DI的关键:

  控制反转,谁控制了谁?--IOC容器控制了对象;控制了什么?--控制了外部资源的获取(对象,文件等);哪些方面的控制被反转了?--获得依赖对象的过程被反转了。

  依赖注入,谁依赖谁?--程序依赖IOC容器;为什么需要依赖?--程序需要IOC容器来提供外部资源;谁注入谁?--IOC容器向程序注入;注入了什么?--注入某个对象所需要的外部资源。

  依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

二.  Spring容器与Bean

1. spring核心容器  

spring的核心容器包括了:Beans、Core、Context、SpEL


    ① core和beans模块提供了整个框架最基础的部分,包括了IOC和DI。

    ② Context建立在Core和Beans模块提供的基础之上:他提供了框架式访问对象的方式

    ③ core、beans、context构成了Spring的骨架

    ④ SpEL:提供了一种强大的用于在运行时操作对象的表达式语言

 org.springframework.beans.factory.BeanFactory是Spring容器的实际代表者,容器负责容纳此前所描述的bean,并对bean进行管理。

2. spring与bean的关系

  Spring容器是Spring的核心,一切SpringBean都存储在Spring容器内。可以说bean是spring核心中的核心。Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息来创建Bean实例,并调用Bean实例的方法来完成“依赖注入”,可以把Spring容器理解成一个大型工厂,Bean就是该工厂的产品,工厂(Spirng容器)里能生产出来什么样的产品(Bean),完全取决于配置文件中的配置。而这个配置是由开发人员创建和维护的。

3. Bean的作用域 

  spring的作用域有singleton,prototype,request,session,globle session。

  这里只讨论常用的singleton和prototype两种作用域

  对于singleton作用域,每次请求同id的Bean都将获得相同的实例,spring容器负责跟踪Bean实例状态,负责维护Bean实例的生命周期。

  对于prototype作用域,程序每次请求同id的Bean会获得新的实例,spring容器只负责创建,一旦创建成功就撒手不管,不再管理Bean实例的生命周期,也不会维护Bean实例的状态。

4. 容器中Bean的生命周期 

  Spring可以管理singleton作用域Bean的生命周期,Spring可以精确地知道singleton域bean何时被创建,何时初始化完成,以及容器何时准备销毁Bean实例。对于singleton作用域的Bean,管理Bean的生命周期行为主要有两个时机:注入依赖关系后,销毁实例之前;具体的管理方法如下:
  Spring提供两种方式在Bean全部属性设置成功后执行特定行为

    使用init-method 属性(代码污染小)
            在类中编写一个方法,在属性中指定该方法在依赖关系设置完成后自动执行。
    实现InitializingBean接口(耦合较高)
            编写afterPropertiesSet()方法的具体实现

  同理,若在Bean销毁之前,执行特定的方法,只需要使用 destroy-method属性或实现DisposableBean接口(实现destroy()方法)

  对于prototype作用域的Bean,Spring容器只负责Bean的创建,当容器创建实例完成后,Bean将完全交给客户端代码管理,容器不再负责其生命周期,Spring容器本身也不知道自己创建了多少个实例,更无从知道这些实例什么时候才会被销毁。

5. Bean标签属性  

  ① id属性:Bean的名称在IOC容器中必须是唯一的。

  ② class属性:指定Bean对应实现类的全类名,即包名加类名,必须有无参构造。

  ③ scope属性: 前面提到过的作用域属性,不指定默认为singleton,即单实例模式。

  ④ name属性:设置<bean>标签的别名,多个别名之间用逗号或空格分开。

  ⑤ parent属性:子类Bean定义它所引用它的父类Bean。子类Bean定义它所引用它的父类Bean。这时前面的class属性失效。子类Bean会继承父类Bean的所有属性,子类Bean也可以覆盖父类Bean的属性。注意:子类Bean和父类Bean是同一个Java类。

  ⑥ abstract属性:用来定义Bean是否为抽象Bean。它表示这个Bean将不会被实例化,一般用于父类Bean,因为父类Bean主要是供子类Bean继承使用。

  ⑦ singleton属性:作用同③,默认为true

  ⑧ lazy-init属性:用来定义这个Bean是否实现懒初始化。如果为“true”,它将在BeanFactory启动时初始化所有的SingletonBean。反之,如果为“false”,它只在Bean请求时才开始创建SingletonBean。

  ⑨ autowire属性:它定义了Bean的自动装载方式。“no”:不使用自动装配功能。“byName”:通过Bean的属性名实现自动装配。“byType”:通过Bean的类型实现自动装配。“constructor”:类似于byType,但它是用于构造函数的参数的自动组装。“autodetect”:通过Bean类的反省机制(introspection)决定是使用“constructor”

  ⑩ dependency-check属性:它用来确保Bean组件通过JavaBean描述的所以依赖关系都得到满足。在与自动装配功能一起使用时,它特别有用。none:不进行依赖检查objects:只做对象间依赖的检查。simple:只做原始类型和String类型依赖的检查。all:对所有类型的依赖进行检查。它包括了前面的objects和simple。

  ⑪ depends-on属性:这个Bean在初始化时依赖的对象,这个对象会在这个Bean初始化之前创建。

  ⑫ init-method属性:用来定义Bean的初始化方法,它会在Bean组装之后调用。它必须是一个无参数的方法。

  ⑬ destroy-method属性:用来定义Bean的销毁方法,它在BeanFactory关闭时调用。同样,它也必须是一个无参数的方法。它只能应用于singletonBean。

  ⑭ factory-method属性:定义创建该Bean对象的工厂方法。它用于下面的“factory-bean”,表示这个Bean是通过工厂方法创建。此时,“class”属性失效。

  ⑮ factory-bean属性:定义创建该Bean对象的工厂类。如果使用了“factory-bean”则“class”属性失效。

三. spring中bean配置

 bean配置有三种方法:

1、配置形式:
①基于xml文件  ②基于注解  ③基于java类

2、配置方式:
①通过全类名(反射)
②通过工厂方法(静态工厂方法、实例工厂方法)
③FactoryBean

3、依赖注入方式:
①属性注入  ②构造器注入

1. 基于xml 全类名 属性注入

    <bean id=\"helloWorld\" class=\"top.arioso.spring.beans.HelloWorld\"> <property name=\"id\"> <value>123456</value> </property> <property name=\"age\" value=\"18\"></property> </bean> property节点:为Bean属性赋值,name为属性名,value对应属性值,属性值要有setter方法 value属性可用子节点value替代

2. 基于xml 全类名 构造注入

    <bean id=\"person\" class=\"top.arioso.spring.beans.Person\"> <constructor-arg type=\"java.lang.String\"> <value>John</value> </constructor-arg> <constructor-arg value=\"America\" index=\"3\"><constructor> <constructor-arg value=\"123456\" type=\"int\"><constructor> <constructor-arg value=\"man\" typ><constructor> <property name=\"id\"> <value>123456</value> </property> <property name=\"age\" value=\"18\"></property> </bean> 要求必须有带参构造 根据value值匹配构造器,匹配不到就匹配下一个 可以用index属性指定带参构造器第几个参数 可以用type属性指定构造函数参数类型的匹配 value属性可用子节点value替代

3. 基于xml 通过工厂配置

  (1) 静态工厂方法配置

    <bean id=\"car\" class=\"top.arioso.spring.factory.staticCarFactory\" factory-method=\"getCar\"> <constructor-arg value=\"BMW\"></constructor-arg> </bean> class:工厂方法全类名 factory-method:要调用工厂方法名 若需要传递参数,使用constructor-arg传值

  (2)实例工厂方法配置

    <bean id=\"carFactory\" class=\"top.arioso.spring.beans.carFactory\"></bean> <bean id=\"car\" factory-bean=\"carFactory\" factory-method=\"getCar\"> <constructor-arg value=\"BMW\"></constructor-arg> </bean> carFactory:工厂的实例 factory-bean: 指向工厂的实例 factory-method:要调用工厂方法名 若需要传递参数,使用constructor-arg传值

  (3)通过FactoryBean配置

 spring框架自身提供的,它需要实现FactoryBean接口,实现代码就必须写在getObject()方法中。

    //java代码 public class SpringFactory implements FactoryBean<Calendar>{ public SpringFactory() { System.out.println(\"我是一个spring工厂类\"); } public Calendar getObject() throws Exception { return Calendar.getInstance(); } public Class<?> getObjectType() { return Calendar.class; } public boolean isSingleton() { return false; }
 //配置文件 <bean id=\"cal\" class=\"springfactory.SpringFactory\"/> 该配置返回的实例是SpringFactory的getObject方法返回的实例。

4. spring配置Bean注入

① 配置字面值
    
    可通过value属性或<value>标签属性注入,
    若字面值包含特殊字符,使用<![CDATA[]]>包裹
    
    spring将属性的空参数当空String,下面给email属性设置了空的String值(\"\")

 

    <bean id=\"nullBean\" class=\"top.arioso.spring.NullBean\"> <property name=\"email\" value=\"\" /> </bean>
   如果要注入null值,可以使用<null />
    <bean id=\"exampleBean\" class=\"top.arioso.spring.NullBean\">
        <property name=\"email\">
            <null />
        </property>
    </bean>

② Bean之间的引用

    <bean id=\"dog\" class=\"top.arioso.hello.Dog\"/> <bean id=\"user\" class=\"top.arioso.hello.User\"> <property name=\"name\" value=\"tony\"/> <property name=\"dog\" ref=\"dog\"></property> </bean>

③ List属性(set同理)

    <bean id=\"user\" class=\"top.arioso.hello.User\"> <property name=\"list\"> <list> <value>北京</value> <value>上海</value> <value>广州</value> <ref bean=\"dog\"/> </list> </property> </bean>

④ map属性

    <bean id=\"user\" class=\"top.arioso.hello.User\"> <property name=\"map\"> <map> <entry key=\"bj\" value=\"北京\"/> <entry key=\"sh\" value=\"上海\"/> </map> </property> </bean>

⑤ Properties属性

    <bean id=\"user\" class=\"top.arioso.hello.User\"> <property name=\"dbParams\"> <props> <prop key=\"username\">root</prop> <prop key=\"password\">root</prop> </props> </property> </bean>

⑥ 独立的集合Bean

    <util:list id=\"computerList\"> <ref bean=\"computer\"/> <bean class=\"top.arioso.spring.collection.ComputerList\"> <constructor-arg value=\"hp\"></constructor-arg> <constructor-arg value=\"dell\"></constructor-arg> <constructor-arg value=\"acer\"></constructor-arg> </bean> </util:list> <bean id=\"User\" class=\"top.arioso.spring.User\"> <property name=\"id\" value=\"2018310\"></property> <property name=\"name\" value=\"Tom\"></property> <property name=\"computers\" value=\"computerList\"></property> </bean>

⑦ 使用p命名空间

 

    <bean id=\"computer\" class=\"top.arioso.spring.Computer\"> <p:brand=\"dell\" p-cpu=\"i7-7700\" p-price=\"7900\"> </bean> 首先需要导入命名空间

5. 基于注解配置Bean

① 注解依赖aop包,要导入aop包。

② Spring 能够从 classpath 下自动扫描(需要配置 context:component-scan )具有特定注解的组件。

    特定的组件包括:

    @Component:基本注解,标识一个受Spring管理的组件。

    @Repository:标识持久层组件。

    @Service:标识业务层组件。

    @Controller:标识控制层组件。

     Spring 对扫描到的组件有默认的命名规则:使用非限定类名,第一个字母小写 (也可以使用value属性指定组件的名称)。

③ 配置<context:component-scan>

<context:component-scan base-package=\"top.arioso.spring.annotation\" resource-pattern=\"service/*.class\"> </context:component-scan> base-package 属性指定Spring扫描的包,Spring将扫描该包及其所有子包,如有多个包,使用逗号隔开。 可以使用 resource-pattern 来过滤特定的类。 <context:exclude-filter>:指定扫描排除哪些类 需设置use-default-filter为false //只扫描有Service注解的类 <context:component-scan resource-pattern=\"controller/*.class\" base-package=\"top.arioso.spring.annotation\" use-default-filters=\"false\"> <context:exclude-filter type=\"annotation\" expression=\"org.springframework.stereotype.Service\"> </context:component-scan> //排除扫描实现了UserRepository的类 <context:component-scan resource-pattern=\"controller/*.class\" base-package=\"top.arioso.spring.annotation\" use-default-filters=\"false\"> <context:exclude-filter type=\"assignable\" expression=\"top.arioso.repository.UserRepository\"> </context:component-scan> <context:include-filter>:指定扫描包含哪些类 //排除扫描有Service注解的类 <context:component-scan resource-pattern=\"controller/*.class\" base-package=\"top.arioso.spring.annotation\" <context:include-filter type=\"annotation\" expression=\"org.springframework.stereotype.Service\"> </context:component-scan> //只扫描实现了UserRepository的类 <context:component-scan resource-pattern=\"controller/*.class\" base-package=\"top.arioso.spring.annotation\" <context:include-filter type=\"assignable\" expression=\"top.arioso.repository.UserRepository\"> </context:component-scan>

6. 使用 @Autowired 注解自动装配Bean

    可以再字段、setter方法、构造器上面使用
    
    默认情况下,当使用 @Autowired 注解的属性,如果在IOC容器中找不到匹配的Bean来装配属性时,会抛出异常。可以使用 required=false 设置某一属性不被设置(即IOC容器不配置匹配的Bean)。
    
    [email protected],当 IOC 容器中存在多个类型匹配的 Bean 时,默认情况下会匹配与属性相同名称的 Bean,若匹配不到则抛出异常。也可以使用 @Qualifier(“Bean名称”) 注解指定注入的Bean。
    
     @Autowired也可以用在数组上,Spring会将所有匹配的Bean自动装配进数组。

     @Autowired也可以用在集合上,Spring会判断该集合的类型,然后自动装配所有类型兼容的Bean。

     @Autowired也可以用在Map上,若key为String类型,Spring将Bean的名称作为key,Bean本身作为值自动装配所有类型兼容的的Bean。
     
     也可以使用 @Resource 或 @Inject 自动装配Bean,功能与 @Autowired 类似,[email protected]

 

 

 

人已赞赏
站长资讯

Logback配置解析

2020-11-9 3:41:42

站长资讯

写作的核心与价值

2020-11-9 3:41:44

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索