Spring学习笔记之IOC


一、Spring的相关概念

1.Spring是开源的轻量级框架

2.Spring核心主要两部分:

(1)aop:面向切面编程,扩展功能不是修改源代码实现。
(2)ioc:控制反转。
例如有一个类,在类里面有个方法(不是静态的方法),调用类里面的方法,创建类的对象,使用对象调用方法,创建类对象的过程,需要new出来对象。

3.Spring是一站式框架

(1)Spring在javaee三层结构中,每一层都提供不同的解决技术
web层:SpringMVC
service层:Spring的ioc
dao层:Spring的jdbc Template

二、Spring的IOC的底层原理

1.漏洞百出的过去

使用创建对象来调用一个类中的方法:

public class User {

    public void add() {
        ...
    }
}

// 在Servlet调用User类里面的方法
// 调用类里面的方法
User user = new User();
user.add();

缺陷:耦合度太高
针对上面的缺陷,于是产生了工厂模式来进行解耦合操作:

public class UserService {

    public void add() {
        ...
    }
}

public class UserServlet {

    UserService s = Factory.getService();
    s.add();
}
// 创建工厂类 
public class Factory {

    public static UserService getService() {
        return new UserService();
    }
}

上述的代码缺陷就是UserServlet与工厂类进行耦合。

2.IOC的原理

public class UserService {

    public void add() {
        ...
    }
}

public classUserServlet {

    // 得到UserService的对象
    // 原始:new创建
    UserService s = UserFactory.getService();
    s.add();
}

第一步:创建xml配置文件,配置需要创建

<!-- 对象类 -->
<bean id="userService" class="com.jxs.UserService"/>

第二步:创建工厂类,使用dom4j解析配置文件+反射

// 返回UserService对象的方法
public static UserService getService() {

    // 1.使用dom4j解析xml文件
    // 根据id值userService,得到id值对应class属性值(类的全路径)
    String classValue = "class属性值";
    // 2.使用反射创建类对象
    Class clazz = Class.forName(classValue);
    // 3.创建类对象
    UserService service = clazz.newInstance();
    return service;
}

这样即使UserService类的路径发生了变化也不会对程序造成影响,从而降低了类之间的耦合度。

三、Spring的bean管理(xml配置文件)

1.bean实例化

在Spring中通过配置文件创建对象

2.bean实例化三种样式

(1)使用类的无参数构造创建(重要)
package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/26. */
public class Bean {

    public void show() {

        System.out.println("hello!");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 使用类的无参数构造创建 -->
<bean id="bean" class="com.jxs.ioc.Bean"></bean>

</beans>

当类中没有无参数的构造时,就会出现异常。

(2)使用静态工厂创建

创建静态的方法,返回类对象

package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/26. */
public class BeanStaticFactory {

    public static Bean getBean() {

        return new 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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 使用静态工厂创建对象 -->
<bean id="bean2" class="com.jxs.ioc.BeanStaticFactory" factory-method="getBean"></bean>

</beans>
(3)使用实例工厂创建

创建不是静态的方法,返回类对象

package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/26. */
public class BeanStaticFactory {

    public Bean getBean() {

        return new 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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- 使用实例工厂创建对象 -->
<bean id="beanStaticFactory" class="com.jxs.ioc.BeanStaticFactory"></bean>
<bean id="bean" class="com.jxs.ioc.BeanStaticFactory" factory-method="getBean"></bean>

</beans>

2.bean标签常用属性

(1)id属性:

起名称,id属性值名称可以任意命名,但是id属性值不能包含特殊符号,例如:!@#$%^&*()_等等,根据id值可以获得配置对象。

(2)class属性:

创建对象所在类的全路径

(3)name属性:

功能和id属性一样。id属性值不能包含特殊符号,但是在name属性值里面可以包含特殊符号,其区别是name属性主要是用于解决一些带符号的命名的遗留问题,现在一般使用id属性。

(4)scope属性

singleton:默认值,对象是单例
prototype:多例
request:创建对象,把对象放到request域里面
session:创建对象,把对象放到session域里面
globalSession:创建对象,把对象放到globalSession域里面

3.属性注入方式

(1)属性注入就是在创建对象的时候向类里面设置值
(2)属性注入的方式介绍(三种方式)
第一种:使用set方法注入

class User {

    private String name;
    public void setName(String name) {

        this.name = name;
    }
}

public class Main {

    User user = new User();
    user.setName("abcd");
}

第二种:有参数构造器注入

class User {

    private String name;
    public User (String name) {

        this.name = name;
    }
}

public class Main {

    User user = new User("abcd");
}

第三种:使用接口注入

public interface Dao {

    public void delete(String name);
}

public class DaoImpl implements Dao {

    private String name;
    public void delete(String name) {

        this.name = name;
    }
}

在Spring框架中,只支持前两种属性注入的方式:

(1)使用set方法注入(重点)

使用set进行属性注入代码示例:

package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/27. */
public class PropertyDemo2 {

    private String userName;

    public void setUserName(String userName) {

        this.userName = userName;
    }

    public void print() {

        System.out.println(userName);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 使用set方法注入属性-->
    <bean id="demo2" class="com.jxs.ioc.PropertyDemo2">
        <!-- 注入属性值 name属性值:类里面定义的属性名称 value属性:设置具体的值-->
        <property name="userName" value="hello!!!">
        </property>
    </bean>
</beans>
(2)有参数构造器注入

有参数构造器进行属性注入代码示例:

package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/26. */
public class PropertyDemo1 {

    private String userName;

    public PropertyDemo1(String userName) {

        this.userName = userName;
    }

    public void print() {

        System.out.println("hhhh" + userName);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 使用有参数构造注入属性 -->
    <bean id="demo1" class="com.jxs.ioc.PropertyDemo1">
        <!-- 使用有参构造注入 -->
        <constructor-arg name="userName" value="wsjxsa">
        </constructor-arg>
    </bean>
</beans>

4.注入对象类型属性

以下列代码为例进行说明(在UserService类中得到UserDao的对象)
实现过程:
(1)在UserService里面把UserDao作为类型属性
(2)生成UserDao类型属性的set方法

package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/27. */
public class UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {

        this.userDao = userDao;
    }

    public void add() {

        System.out.println("This is Service add operation");
        // UserDao dao = new UserDao();
        // dao.add();
        userDao.add();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 使用set方法注入对象类型属性-->
    <bean id="userDao" class="com.jxs.ioc.UserDao"></bean>

    <bean id="userService" class="com.jxs.ioc.UserService">
        <!-- 注入dao对象 name属性值:UserService类中属性名称 不写value属性,因为此时的类型是一个对象 ref属性值:UserDao配置bean标签中的id值-->
        <property name="userDao" ref="userDao"></property>
    </bean>

</beans>

5.P名称空间注入

代码示例:

package com.jxs.ioc;

/** * Created by jiangxs on 2018/3/27. */
public class Person {

    private String personName;

    public void setPersonName(String personName) {

        this.personName = personName;
    }

    public void print() {

        System.out.println("name is "+personName);
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- p名称空间注入 -->
    <bean id="person" class="com.jxs.ioc.Person" p:personName="jxs"></bean>
</beans>

测试代码:

package com.jxs.ioc;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/** * Created by jiangxs on 2018/3/26. */
public class TestIOC {

    @Test
    public void testPerson() {

        // 1.加载Spring配置文件,根据配置文件的配置创建对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");

        // 2.得到配置创建对象
        Person person = (Person) context.getBean("person");
        person.print();
    }
}

测试结果:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

name is jxs

Process finished with exit code 0

6.注入复杂类型

(1)数组
(2)list集合
(3)map集合
(4)properties类型
代码示例:

package com.jxs.ioc;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/** * Created by jiangxs on 2018/3/27. */
public class Person {

    private String personName;
    private String[] arrays;
    private List<String> list;
    private Map<String, Integer> map;
    private Properties properties;

    public void setArrays(String[] arrays) {

        this.arrays = arrays;
    }

    public void setList(List<String> list) {

        this.list = list;
    }

    public void setMap(Map<String, Integer> map) {

        this.map = map;
    }

    public void setProperties(Properties properties) {

        this.properties = properties;
    }

    public void setPersonName(String personName) {

        this.personName = personName;
    }

    public void printComplex() {

        System.out.println("arrays:"+arrays);
        System.out.println("list:"+list);
        System.out.println("map:"+map);
        System.out.println("properties:"+properties);
    }
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 注入复杂类型属性值 -->
    <bean id="person" class="com.jxs.ioc.Person">
        <!-- 数组 -->
        <property name="arrays">
            <list>
                <value>jxs</value>
                <value>哈哈</value>
                <value>2018-3-27</value>
            </list>
        </property>
        <!-- list集合 -->
        <property name="list">
            <list>
                <value>这是</value>
                <value>集合</value>
            </list>
        </property>
        <!-- map集合 -->
        <property name="map">
            <map>
                <entry key="jxs" value="10"/>
                <entry key="jmf" value="11"/>
                <entry key="wrq" value="1"/>
            </map>
        </property>
        <!-- properties -->
        <property name="properties">
            <props>
                <prop key="url">com.mysql.jdbc.Driver</prop>
                <prop key="username">root</prop>
                <prop key="psaaword">root</prop>
            </props>
        </property>
    </bean>

</beans>

测试代码:

package com.jxs.ioc;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/** * Created by jiangxs on 2018/3/26. */
public class TestIOC {

    @Test
    public void testPerson() {

        // 1.加载Spring配置文件,根据配置文件的配置创建对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");

        // 2.得到配置创建对象
        Person person = (Person) context.getBean("person");

        person.printComplex();
    }
}

测试结果:

log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

arrays:[Ljava.lang.String;@31f924f5
list:[这是, 集合]
map:{jxs=10, jmf=11, wrq=1}
properties{url=com.mysql.jdbc.Driver, psaaword=root, username=root}

7.IOC和DI的区别

(1)IOC:控制反转,把对象创建交给Spring进行配置。其思想是反转资源获取的方向。IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
传统的资源查找要求组件向发起请求查找资源,作为回应,容器适时的返回资源,而应用了IoC之后,则是容器主动将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源,这种行为也被称为查找的被动形式。
(2)DI:依赖注入,向类里面的属性中设置值IOC的另一种表述方式:即组件以一些预先定义好的方式(如:setter方法)接受来自容器的资源注入。相对于IOC而言,这种表述更为直接。
关系:依赖注入不能单独存在,需要在IOC的基础之上完成操作。依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。

四、Spring整合Web项目原理

1.加载Spring核心配置文件

// 加载Spring核心配置文件,根据配置文件的配置创建对象
ApplicationContext context = 
                        new ClassPathXmlApplicationContext("bean1.xml");

这种new对象的方式,功能上可以实现,但是效率很低

2.实现思想

把加载配置文件和创建对象的过程在服务器启动时完成

3.实现原理

(1)ServletContext对象
(2)监听器
(3)具体使用:

  • 在服务器启动的时候,为每个项目创建一个ServletContext对象
  • 在ServletContext对象创建的时候,使用监听器可以具体到ServletContext对象在什么时候创建(监听器ServletContextListener的contextInitialized()方法会执行,ServletContext对象会创建,然后放入ServletContext的对象中)
  • 使用监听器监听到ServletContext对象创建的时候,加载Spring配置文件,把配置文件配置的对象进行创建
  • 把创建出来的对象放到ServletContext域里面(setAttribute方法)
  • 获取对象的时候,到ServletContext域得到(getAttribute方法)
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



猜您在找
Spring IoC学习笔记(二) Spring学习笔记(一)——IOC Spring学习笔记(一)——IOC Spring学习笔记--Spring IOC Spring学习笔记之IoC容器
智能推荐
 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告