手把手教你学spring之springIOC(二)

spring IOC (Inversion of Control,控制反转)

从这一小节开始,我们进入spring的学习

在学习之前我把之前所有的代码都共享出来,方便大家学习 探讨。

代码地址:

https://gitee.com/cgyspace/code-demos

选用的spring版本: 5.2.13.RELEASE

依赖注入
构造器注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.cgy.spring5.ioc.service.UserService">
        <constructor-arg ref="userDao"/>
    </bean>
    <bean id="userDao" class="com.cgy.spring5.ioc.dao.UserDao">

    </bean>
</beans>
package com.cgy.spring5.ioc.service;

import com.cgy.spring5.ioc.dao.UserDao;
import com.cgy.spring5.ioc.entity.User;

public class UserService {

    private UserDao userDao;

    public UserService() {

    }

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User getUser() {
        return userDao.getUserByName("张三");
    }
}

说明: 在利用构造器注入的时候,我习惯再加一个无惨构造器。因为有参构造器会覆盖无参构造器,在很多场景下,无参构造器会被框架所调用,如果没有的话会导致程序报错。

测试类

package com.cgy.spring5.ioc;

import com.alibaba.fastjson.JSON;
import com.cgy.spring5.ioc.entity.User;
import com.cgy.spring5.ioc.service.ClientService;
import com.cgy.spring5.ioc.service.LoginService;
import com.cgy.spring5.ioc.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
        UserService bean = context.getBean(UserService.class);
        System.out.println(JSON.toJSONString(bean.getUser()));

    }
}

执行结果:

在这里插入图片描述

多参构造器

指定参数类型

	<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean name="user" class="com.cgy.spring5.ioc.entity.User">
  <constructor-arg type="java.lang.String" value="张三"/>
  <constructor-arg type="int" value="16"/>
  <constructor-arg  type="java.lang.String" value="123456"/>

 </bean>
</beans>

指定参数索引

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
 <!--特别要注意的是 当用索引的时候 spring会把所有的value值当做String 来处理 -->
 <bean name="user" class="com.cgy.spring5.ioc.entity.User">
  <constructor-arg  index="0" value="张三"/>
  <constructor-arg index="1" value="16"/>


 </bean>
</beans>

setter方法注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.cgy.spring5.ioc.entity.User"/>
<bean name="userDao" class="com.cgy.spring5.ioc.dao.UserDao"/>
    <bean name="userService" class="com.cgy.spring5.ioc.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>
</beans>
package com.cgy.spring5.ioc.service;

import com.cgy.spring5.ioc.dao.UserDao;
import com.cgy.spring5.ioc.entity.User;

public class UserService {

    private UserDao userDao;

    public UserService() {
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public User getUser(){
        return userDao.getUserByName("张三");
    }
}

注入Collections
<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">[emailprotected]</prop>
            <prop key="support">[emailprotected]</prop>
            <prop key="development">[emailprotected]</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

注入null值

<bean class="ExampleBean">
    <property name="email">
        <null/>
    </property>
</bean>

懒加载

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean name="userService" class="com.cgy.spring5.ioc.service.UserService" lazy-init="true"/>

</beans>

自动装配

ModeExplanation
no(默认)无自动装配。 Bean 引用必须由ref元素定义。对于大型部署,建议不要更改默认设置,因为明确指定协作者可以提供更好的控制和清晰度。在某种程度上,它记录了系统的结构。
byName按属性名称自动装配。 Spring 寻找与需要自动装配的属性同名的 bean。例如,如果一个 bean 定义被设置为按名称自动装配,并且包含一个master属性(即,它具有setMaster(..)方法),那么 Spring 将查找一个名为master的 bean 定义并使用它来设置属性。
byType如果容器中恰好存在一个该属性类型的 bean,则使该属性自动装配。如果存在多个错误,则会引发致命异常,这表明您可能不对该 bean 使用byType自动装配。如果没有匹配的 bean,则什么也不会发生(未设置该属性)。
constructor类似于byType,但适用于构造函数参数。如果容器中不存在构造函数参数类型的一个 bean,则将引发致命错误。

bean的作用范围

ScopeDescription
singleton(默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype将单个 bean 定义的作用域限定为任意数量的对象实例。
request将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
说明

request session application websocket 作用域只在web环境中有效

如果你使用的是springmvc的DispatcherServlet,则不用做任何处理,DispatcherServlet已经自己处理了这些作用域的底层实现

如果你用的是非springmvc的web技术 比如jsf 或者Struts,这时需要增加配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" >
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

 </web-app>

如果你用的是 Servlet 3.0以上环境,则可以用WebApplicationInitializer 进行编程完成监听器的注册

另外,如果你的环境配置listener有问题,无法注册监听器你还可以使用过滤器完成此功能

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" >
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 </web-app>

DispatcherServletRequestContextListenerRequestContextFilter都做完全相同的事情,即将 HTTP 请求对象绑定到正在为该请求提供服务的Thread上。这使得在请求链和会话范围内的 Bean 可以在调用链的更下游使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cgycro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值