Spring框架之IOC

来源:互联网 发布:7.0魔兽数据库 编辑:程序博客网 时间:2024/06/13 13:09

IOC: 就是控制反转

    -----------        原来是自己创建对象,现在交给spring容器创建对象

Spirng创建对象的原理:

    --------------        加载核心配置文件 逐行解析xml文件 当解析到bean时开始创建对象(利用反射创建对象) 将创建好的对象存入map中  key就是id 

Spring容器获取对象的方式:

    ----------------        配置文件的写法:`<bean id=" " class="  "> <bean/>

(1)通过ID获取对象

        context.getBean(" id ");

(2)通过class类型获取对象(风险)

        context.getBean( 类名.class);        因为spring以map的形式存储对象,可以有重复的value 当value的值相同时就会报异常

Spring创建对象的四种方式:

    ----------------

(1)无参构造创建对象: 是以反射方法

        要有一个无参构造方法,当类中不写无参构造时,系统默认创建一个无参构造,如果要自己写构造方法,必须添加一个无参构造方法

(2)静态工厂

        当对象不能通过反射直接创建时,就用静态工厂的方法        配置文件中的写法:        <bean id=" " class=" " factory-method=" 静态方法 " />

(3)实例工厂

        factory-bean=“ ” factory—method=“方法”        一般使用通过对象.方法 获取一个对象 时使用        <bean id="" class=""/>        <bean id="" factory-bean=“ ” factory—method=“方法”>        (4)Spring工厂 实现FactoryBean接口  通过里面的getObject()

单例和多例:

    ------        单例对象是如何存储?            单例对象一般是存放在Spring的map集合中,和Spring容器同生共死        多例对象是如何存储?            多例对象默认为懒加载,用户每调用一次对象Spring容器就会创建一个对象 ,Spring对象不负责维护多例对象的生命周期,谁调用谁负责.        通过scope改变单例和多例。    懒加载机制:    ------        两种方法:         全局配置懒加载生效:default-lazy-init="true"         局部配置懒加载生效:            lazy-init="false" 不生效            lazy-init="true" 生效            lazy-init="default" 看全局的  如果没有全局 就默认不生效

DI 依赖注入

    -------

1.set方法注入

            类中必须有set方法,配置文件中通过property为属性赋值 name的获取方法: 去掉set 将紧跟的后面的字母变为小写                (1)简单类型:                  (2)集合:                (3)配置文件:具体代码如下          ```    <bean id="user" class="pojo.User" >            <!--为简单属性赋值  -->            <property name="id" value="100"/>            <property name="name" value="孙尚香"/>             <!--为集合赋值  -->            <property name="list">    <!--ArrayList  -->                <list>                    <value>上单</value>                    <value>中单</value>                    <value>打野</value>                    <value>射手</value>                    <value>肉盾</value>                </list>            </property>            <property name="set">                <set>                    <value>一</value>                    <value>一</value>                    <value>二</value>                </set>            </property>            <property name="map">                <map>                    <entry key="1" value="1"/>                    <entry key="2" value="2"/>                    <entry key="3" value="3"/>                </map>            </property>            <!--为配置文件赋值-->            <property name="pro">                <props>                    <prop key="一">一</prop>                    <prop key="二">二</prop>                    <prop key="三">三</prop>                </props>            </property>        </bean>    ```            (4)引用                 两个步骤:                    (1)先将对象创建出来                    (2)添加引用    ```    <bean id="cat" class="pojo.Cat"></bean>        <bean id="user" class="pojo.User" >            <!-- ref="" 表示对象的引用  -->            <property name="dog" ref="dog"/>        </bean>    ```

2.构造方法注入

            必须写构造方法,先写无参构造.代码如下:    ```    构造方法为:        //3个参数构造        public User(Integer id, String arg0, Dog dog) {            super();            this.id = id;            this.name = arg0;            this.dog = dog;        }    配置文件为:        <!--构造方法注入 3个参数 -->        <bean id="user" class="pojo.User">            <!--代表一个参数                  index="0" 参数的下标 从0开始                name=""   参数名称                ref=""    对象的引用                value="" 属性的值            -->            <constructor-arg index="0"  value="1"/>            <constructor-arg index="1" value="王者荣耀"/>            <constructor-arg index="2" name="dog" ref="dog"/>        </bean>    ```            注入方式分析:                程序员自己写的代码set注入较多,如果是软件架构使用构造注入居多            注意:                (1)构造函数中参数一定要和配置文件中的参数个数相同,否则会报could not resolve constructor异常                (2)当没有导包的时候,java中不会维护形参的名称,所以使用name属性进行注入时,会发生风险,所以用index进行注入

对象注入简化:

    ------------    autowire标签 自动装配,为引用类型自动赋值.需要一来set方法,也就是说类中必须有set方法!    分为两种方式:                autowire="byName" 实现原理:                    1.找到当前对象的set方法                    2.将方法进行变形 将set去掉 首字母换成小写                    3.通过变形后的名字找到bean中所有的id,如果一致就能成功注入                    4.如果根据id进行匹配,如果没有成功,不能入住,为null,有风险,不建议        autowire="byType" 实现原理:                    1.找到当前对象的set方法                    2.找到参数类型                      3.根据class匹配bean中class 如果找到就注入成功,否则就返回null;    ```    代码实现:一般在约束标签中添加,省去了<property name="dog" ref="dog"/>        default-autowire="byType"    ```

属性注解

    ---------       优点:省去了对象的注入标签,在类中的引用对象中添加属性注解,省去了对象注入简化.       实现方法:在配置文件中添加    ```    <!--开启属性注解  -->     <context:annotation-config/>     ```       分类:          (1) @Autowired注解                  实现原理:                   Autowired注解有两种装配方式为byName,byType. 根据指定的对象的匹配bean中id,如果成功                  则成功,如果失败根据class类型匹配 都失败证明bean中没有指定的数据,报错,Spring容器启动                  失败,给用户更好的体验,报出的异常如下图所示:

异常信息

        ```        //代码实现:        @Autowired            private Dog dog;            @Autowired            private Cat cat;        ```        (2)为了解决上面的问题,引入一个标签@Qualifier(value="id名字")为指定id进行注入            注意点:          ```        @Autowired //两个注解都是spring提供的        @Qualifier(value="dogB")  //表示强制指定ID进行注入  2个注解必须一起使用,否则报错        private Dog dog;        ```        (3)@Resource 注解 综合了以上两种的优点可以直接指定id注入        ```        //代码实现:        @Resource(name="dogA")        private Dog dog;        ```        说明:                1.如果是单个项目使用任意一个都可以                2.如果是多个项目,则使用@Autowired

类的注解 @component

    目的:为了省去配置文件中的<bean>标签    实现方法:            在配置文件中添加    ```        <!--开启包扫描             base-package="pojo"  指定的包路径            如果包的个数较多,使用“,”号分割            只要给定了包路径,就会扫描给定包的全部子孙包            只要开启包扫描   默认开启属性注解         -->        <context:component-scan base-package="pojo"/>        //在类中添加        @Component          public class User {        @Autowired        private Dog dog;        }
                同类型的注解:                @Scope(value="protoType")  //对象的单例和多例                @Lazy(true)                //表示懒加载                @Component              //万能注解                @Controller               //控制层的注解                @Service                       //业务层注解                @Repository               //持久层的注解                功能上和@Component没有任何差别,为了让程序员编程更加的明确,定义的。                 @Component(value="tom") 指定Bean的Id为tom注解的使用原理:        1.当容器启动时,首先会加载spring的配置文件。        2.根据包扫描指定的包路径spring会扫描当前包下的全部子孙包        3.在扫描时如果发现类上还有@Component注解,则会根据spring的规则为其创建对象。将对象创建通过反射创建完成后,存入spring所维护的map中,key就是类名首                字母小写。value就是生成的对象。则会发出报错信息。容器启动失败。        4.如果类中需要进行对象注入则在创建对象的之后,自动的根据注解的匹配规则为其注入正确的对象,如果对象正确注入。则spring返回正确的对象如果注入有误,            spring则会发出报错信息。容器启动失败。ID生成策略    默认规则:看类名字的第二个字母,当第二个字母为大写时,则保持类名不变,如果第二个字母小写,类名的首字母才会小写    回显bean中的id    实现接口BeanNameAware
        //代码实现:        public class Test implements BeanNameAware{            @Override            public void setBeanName(String name) {                System.out.println("当前bean的id为"+name);            }        }
为属性赋值=====        为基本类型赋值        ```        @Value("100")                private Integer id;        ```        为基本类型动态赋值:
<context:property-placeholder location="classpath:/配置文件的名字"/>    //类里面:    @Value("${ 配置文件中的key}")    private String name;    //配置文件xxx.properties的写法:    key=value
为集合赋值    引入约束条件util    定义集合    属性引入:
 //配置文件的写法    <util:list id= "list">        <value>1</value>        <value>2</value>        <value>3</value>    </util:list>   //属性引入:    @Value("#{list}")//注意和基本类型动态赋值的区别    private List list;

“`

原创粉丝点击