spring框架(IOC)_01

1.spring的介绍

spring的2大核心思想:
ioc: 控制反转,就是工厂模式。 将对象的创建和销毁交给了spring
aop:面向切面的编程,就是动态代理。 在不修改源码的情况下,对功能进行增强。

2.spring的ioc

2.1 工厂模式

2.1.2 反射解耦

基于多个实现类需要进行功能切换,我们只需要修改配置文件,不需要改java代码,所以不需要重新编译。

UserServlet

package com.itheima.web;

import com.itheima.service.UserService;
import com.itheima.service.impl.UserServiceImpl;
import com.itheima.service.impl.UserServiceImpl2;

import java.util.ResourceBundle;

public class UserServlet {

    public static void main(String[] args) {
        //请求过来,调用servlet的service

        //UserService userService = new UserServiceImpl2();

        //读取配置文件的内容
        ResourceBundle rb = ResourceBundle.getBundle("beans");
        String classPath = rb.getString("classPath");

        UserService userService = null;
        try {

            userService = (UserService) Class.forName(classPath).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        userService.login();
    }
}

UserService

package com.itheima.service;

public interface UserService {
    public void login();
}

UserServiceImpl

package com.itheima.service.impl;

import com.itheima.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public void login() {
        System.out.println("登录功能");
    }
}

UserServiceImpl2

package com.itheima.service.impl;

import com.itheima.service.UserService;

public class UserServiceImpl2 implements UserService {
    @Override
    public void login() {
        System.out.println("登录功能扩展");
    }
}

beans.properties

classPath=com.itheima.service.impl.UserServiceImpl2

2.1.2 多例工厂模式

bean.properties

userService=com.it.service.impl.UserServiceImpl
roleService=com.it.service.impl.RoleServiceImpl

BeansFacoty

package com.it.utils;

import com.it.service.RoleService;
import com.it.service.UserService;

import java.util.ResourceBundle;

/**
 * 工厂模式:专门用来创建java对象的工具类。
 *
 *      将java对象的创建由new的方式 替换成了  反射+配置的方式来创建对象。
 *
 *
 *    工厂模式的好处:
 *      1.解耦
 *      2.可以对java中的对象进行管理。
 *
 *
 *    注意:
 *      在没有解耦的情况下,我们以前使用对象,都是自己new
 *      现在有了工厂模式,我们使用对象,都是工厂去创建,我们从工厂去获取。
 *      对象的创建权利由我们自己创建,交给了工厂创建。这就是ioc
 *
 */
public class BeansFactory {

    public static Object getBean(String beanName){
        //1.读取配置
        ResourceBundle rb = ResourceBundle.getBundle("beans");
        String classPath = rb.getString(beanName);
        //2.反射机制创建对象
        Object obj = null;
        try {
            obj = Class.forName(classPath).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;
    }

    public static void main(String[] args) {
        UserService userService = (UserService) getBean("userService");
        System.out.println(userService);
        RoleService roleService = (RoleService)getBean("roleService");
        System.out.println(roleService);
    }
}

2.1.3 单例工厂

package com.it.utils;

import com.it.service.RoleService;
import com.it.service.UserService;

import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Map;

/**
 * 工厂模式:专门用来创建java对象的工具类。
 *
 *      将java对象的创建由new的方式 替换成了  反射+配置的方式来创建对象。
 *
 *
 *    工厂模式的好处:
 *      1.解耦
 *      2.可以对java中的对象进行管理。
 *              单例和多例
 *
 *              单例:一个类创建的对象只有一个。节省资源。
 *              多例:一个类创建的对象可以有多个。
 *
 *
 *              如果存在线程安全问题的情况下,不能采用单例。
 *              什么情况下会出现线程安全问题?
 *              1.多并发
 *              2.多个线程抢占一个资源,并且做了修改。
 *
 *
 *    注意:
 *      在没有解耦的情况下,我们以前使用对象,都是自己new
 *      现在有了工厂模式,我们使用对象,都是工厂去创建,我们从工厂去获取。
 *      对象的创建权利由我们自己创建,交给了工厂创建。这就是ioc
 *
 */
public class BeansFactory {

    /**
     * 多例工厂
     *
     *  此时我们的工厂创建的是service对象
     *   1.是否是并发的?  是。
     *   2.是否涉及多个线程抢占一个资源,并且修改了service。  不涉及service的成员变量的更改
     *
     *   是否存在线程安全问题呢?不存在
     *   使用单例,性能更好。
     *
     *
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        //1.读取配置
        ResourceBundle rb = ResourceBundle.getBundle("beans");
        String classPath = rb.getString(beanName);
        //2.反射机制创建对象
        Object obj = null;
        try {
            obj = Class.forName(classPath).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;
    }


    private static Map<String,Object> beansMap = new HashMap<>();
    /**
     *  单例工厂
     *      第一次创建对象,后续都是获取第一次创建的对象。
     *
     *      1.声明变量,接受创建的对象。
     *      2.优先从map中获取,如果有,直接返回。如果没有,创建
     *
     *
     *
     *
     *
     *  @param beanName   需要创建的对象的名字
     *  @return   返回创建的对象,如果对象创建失败,返回null
     */
    public static Object getBean2(String beanName){

        Object obj = beansMap.get(beanName);
        if(obj==null){
            //第一次创建
            //1.读取配置
            ResourceBundle rb = ResourceBundle.getBundle("beans");
            String classPath = rb.getString(beanName);
            //2.反射机制创建对象
            try {
                obj = Class.forName(classPath).newInstance();
                //保存到map,方便下次直接获取
                beansMap.put(beanName,obj);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        return obj;
    }



    public static void main(String[] args) {
        UserService userService = (UserService) getBean2("userService");
        UserService userService2 = (UserService) getBean2("userService");
        System.out.println(userService);
        System.out.println(userService2);
//        RoleService roleService = (RoleService)getBean("roleService");
//        System.out.println(roleService);
    }
}

2.1.4 单例工厂和多例工厂的区别

多例:
	1.什么时候用,什么时候创建。
	2.一旦创建成功,工厂想要再次操作这个对象,可不可以?  不可以的。
单例:
	1.可以第一次用的时候创建,也可以先全部创建好。
	2.一旦创建成功,工厂想要再次操作这个对象,可不可以?   可以,只要从map中获取即可。

2.2 spring的使用

2.2.1 spring的入门

步骤:
1.引入spring-context 依赖,spring的ioc核心依赖。
2.编译spring的配置xml
3.通过spring工厂获取对象

1.pom.xml引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.6.RELEASE</version>
    </dependency>
</dependencies>

2.编写spring的applicationContext.xml配置

配置文件做成模板

<?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 definitions here -->

    <bean id="userService" class="com.it.service.impl.UserServiceImpl"></bean>

</beans>

3.通过spring的工厂获取对象

package com.it.test;

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

public class SpringTest {
    public static void main(String[] args) {

        //1.创建spring的工厂
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        //2.通过spring的工厂获取对象
        Object userService = ac.getBean("userService");
        System.out.println(userService);

    }
}

2.2.2 spring的工厂类(了解)

BeanFactory: spring工厂的顶层接口
applicationContext: BeanFactory的子接口
		FileSystemXmlApplicationContext: 基于绝对路径的xml的工厂
		ClassPathXmlApplicationContext: 基于相对路径的xml的工厂

2者的区别就是:创建(单例)对象的时间不一样
BeanFactory:    什么时候使用,什么时候创建
applicationContext:   工厂初始化时,全部创建成功

2.2.3 spring的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 definitions here -->

    <!--
        bean标签:  创建对象,将对象装配到spring容器(泛指spring工厂类)。

            id: 对象的唯一标识
            class:实现类的路径,底层就是通过反射机制创建对象的。

            init-method:  对象创建时,要调用的初始化方法
            destroy-method:  对象销毁时,要调用的销毁方法

            scope:
                singleton: 单例(默认)
                prototype: 多例

            对象的生命周期:


                applicationContext: 工厂初始化时,对象就创建完毕。(单例情况下)
                单例:
                    工厂初始化时创建对象。
                    只要工厂存在,对象就存在。
                    工厂销毁,对象销毁。
                多例:
                    什么时候用,什么时候创建。
                    工厂存在,对象存在。
                    工厂销毁,对象不销毁。对象只能等待垃圾回收机制回收。

    -->

    <bean id="userService" scope="prototype" init-method="init" destroy-method="destroy" class="com.it.service.impl.UserServiceImpl"></bean>

</beans>

test:

package com.it.test;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class SpringTest {
    public static void main(String[] args) {

        System.out.println("**************工厂初始化start*********************");
        //1.创建spring的工厂
        //ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//        Resource resource = new ClassPathResource("applicationContext.xml");
//        BeanFactory ac = new XmlBeanFactory(resource);

        System.out.println("**************工厂初始化end*********************");
        //2.通过spring的工厂获取对象
        Object userService = ac.getBean("userService");
        Object userService2 = ac.getBean("userService");
        System.out.println(userService);
        System.out.println(userService2);

        //销毁工厂
        System.out.println("*************销毁工厂*********************8");
        ac.close();

    }
}

2.2.4 spring创建对象的3种方式

1.默认无参构造
2.工厂类的静态方法
3.工厂类的动态方法

applicationContext.xml

<?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创建对象的4种方式
            1.默认无参构造
            2.工厂类的静态方法
            3.工厂类的动态方法


            4.BeanFactory接口方式,ssm整合再去介绍
    -->
    <!-- 默认无参构造方式-->
    <bean id="userService" class="com.it.service.impl.UserServiceImpl"></bean>


    <!-- 工厂类的静态方式 -->
    <bean id="userService2" class="com.it.utils.BeanFactory" factory-method="getUserService"></bean>


    <!-- 工厂类的动态方法-->
    <bean id="factoryBean2" class="com.it.utils.BeanFactory2"></bean>
    <bean id="userService3" factory-bean="factoryBean2" factory-method="getUserService" ></bean>

</beans>

UserServiceImpl

package com.it.service.impl;

import com.it.service.UserService;

public class UserServiceImpl implements UserService {



    public UserServiceImpl() {
        System.out.println("UserServiceImpl的无参构造被调用了");
    }

}

BeanFactory工厂类的静态方法

package com.it.utils;

import com.it.service.UserService;
import com.it.service.impl.UserServiceImpl;

public class BeanFactory {

    public static UserService getUserService(){
        System.out.println("工厂类的静态方法");
        return new UserServiceImpl();
    }
}

BeansFactroy2工厂类的动态方法

package com.it.utils;

import com.it.service.UserService;
import com.it.service.impl.UserServiceImpl;

public class BeanFactory2 {

    public  UserService getUserService(){
        System.out.println("工厂类的静态方法");
        return new UserServiceImpl();
    }
}

2.2.5 spring的DI

Dependency Injection (依赖注入):spring创建对象的时候,给对象的属性赋值,就是依赖注入。
2.2.5.1 有参构造

UserDao

package com.it.dao;

public interface UserDao {

    public void findUserByUser();
}

UserDaoImpl

package com.it.dao.impl;

import com.it.dao.UserDao;

public class UserDaoImpl implements UserDao {
    @Override
    public void findUserByUser() {
        System.out.println("查询用户信息");
    }
}

UserService

package com.it.service;

public interface UserService {

    public void login();
}

UserServiceImpl

package com.it.service.impl;

import com.it.dao.UserDao;
import com.it.dao.impl.UserDaoImpl;
import com.it.service.UserService;

public class UserServiceImpl implements UserService {



    private String username;
    private Integer age;
    private String game;
    private UserDao userDao;

    public UserServiceImpl(String username, Integer age, String game, UserDao userDao) {
        this.username = username;
        this.age = age;
        this.game = game;
        this.userDao = userDao;
    }

    public UserServiceImpl() {
    }

    @Override
    public void login() {
        userDao.findUserByUser();
    }
}

Test

package com.it.test;

import com.it.service.UserService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class SpringTest {
    //这是一个servlet
    public static void main(String[] args) {

        //调用service
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        UserService userService = (UserService)ac.getBean("userService3");
        userService.login();

    }
}

applicationContext.xml

<?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.it.service.impl.UserServiceImpl">
        <!--
            给哪个属性赋什么值

            确定属性
                name: 通过属性名确定属性
                type: 通过属性的类型确定属性
                index: 通过索引来确定属性

            赋值:
                value:基本类型的赋值
                ref: 引用型类型的赋值
        -->
        <constructor-arg name="age" value="23"  ></constructor-arg>
        <constructor-arg name="game" value="LOL"></constructor-arg>
        <constructor-arg name="username" value="张三"></constructor-arg>
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
    </bean>

    <!-- 有参构造方式-->
    <bean id="userService2" class="com.it.service.impl.UserServiceImpl">

        <constructor-arg index="1" value="23"  ></constructor-arg>
        <constructor-arg index="2" value="LOL"></constructor-arg>
        <constructor-arg index="0" value="张四"></constructor-arg>
        <constructor-arg index="3" ref="userDao"></constructor-arg>
    </bean>

    <!-- 有参构造方式-->
    <bean id="userService3" class="com.it.service.impl.UserServiceImpl">

        <constructor-arg type="java.lang.Integer" value="23"  ></constructor-arg>
        <constructor-arg type="java.lang.String" value="王五"></constructor-arg>
        <constructor-arg type="java.lang.String" value="LOL"></constructor-arg>
        <constructor-arg type="com.it.dao.UserDao" ref="userDao"></constructor-arg>
    </bean>

    <bean id="userDao" class="com.it.dao.impl.UserDaoImpl"></bean>
</beans>
2.2.5.2 set方法

UserServiceImpl

package com.it.service.impl;

import com.it.dao.UserDao;
import com.it.dao.impl.UserDaoImpl;
import com.it.service.UserService;

public class UserServiceImpl implements UserService {



    private String username;
    private Integer age;
    private String game;
    private UserDao userDao;

    public UserServiceImpl(String username, Integer age, String game, UserDao userDao) {
        this.username = username;
        this.age = age;
        this.game = game;
        this.userDao = userDao;
    }


    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setGame(String game) {
        this.game = game;
    }

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



    public UserServiceImpl() {
    }

    @Override
    public void login() {
        userDao.findUserByUser();
    }
}

applicationContext.xml

<!-- 属性的set方法 -->
<bean id="userService4" class="com.it.service.impl.UserServiceImpl">

    <!--
        name:用来确定属性的。
            name属性的值是set的方法名去掉set后的驼峰命名名字。
        value:基本类型的属性赋值
        ref:引用型类型的属性赋值
    -->
    <property name="username" value="赵六"></property>
    <property name="age" value="25"></property>
    <property name="game" value="王者荣耀"></property>
    <property name="userDao" ref="userDao"></property>
</bean>
2.2.5.3 依赖注入的简写方式(了解)

c名称空间(原理采用的是有参构造)

xmlns:c="http://www.springframework.org/schema/c"

p名称空间 (原理采用的是set方法)


xmlns:p="http://www.springframework.org/schema/p"
<!-- c名称空间-->
<bean id="userService5" class="com.it.service.impl.UserServiceImpl"
      c:age="18" c:game="王者荣耀" c:username="c罗" c:userDao-ref="userDao"></bean>

<!-- p名称空间-->
<bean id="userService6" class="com.it.service.impl.UserServiceImpl"
        p:age="18" p:username="柳岩" p:game="足球" p:userDao-ref="userDao"></bean>
2.2.5.4 复杂类型的注入

UserServiceImpl2

package com.it.service.impl;

import com.it.dao.UserDao;
import com.it.service.UserService;

import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Map;

public class UserServiceImpl2 implements UserService {


    private String[] gameNames;
    private List<String> dogType;
    private Set<String> catType;
    private Map<String,String> map;


    public void setGameNames(String[] gameNames) {
        this.gameNames = gameNames;
    }

    public void setDogType(List<String> dogType) {
        this.dogType = dogType;
    }

    public void setCatType(Set<String> catType) {
        this.catType = catType;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public void login(){
    }
}

applicationContext.xml

<!--复杂类型的注入-->
<bean id="userService7" class="com.it.service.impl.UserServiceImpl2">
    <property name="gameNames">
        <array>
            <value>LOL</value>
            <value>打豆豆</value>
            <value>王者荣耀</value>
        </array>
    </property>
    <property name="dogType">
        <list>
            <value>泰日天</value>
            <value>二哈</value>
            <value>中华田园犬</value>
        </list>
    </property>
    <property name="catType">
        <set>
            <value>蓝猫</value>
            <value>橘猫</value>
            <value>加菲猫</value>
        </set>
    </property>
    <property name="map">
       <map>
           <entry value="bb" key="aa"></entry>
       </map>
    </property>

</bean>

3.总结

理解了解
1.工厂模式,理解,关键单例工厂和多例工厂的区别,就是在于单例工厂有一个map集合保存bean对象,
   多例没有,创建之后直接返回。
2.spring的工厂类
	单例模式下,创建对象的时间节点不一样。
	BeanFactory: 顶层接口,什么时候用,什么时候创建对象。
	ApplicationContext:BeanFactory的子接口。工厂初始化时创建

掌握的
1.spring的2大核心思想
	ioc: 控制反转,对象的创建由我们自己new,换成spring工厂创建
	aop: 面向切面的编程,底层就是动态代理,在不修改源码的情况下增强功能
2.spring的入门步骤
	a.引入spring-context依赖
	b.编写spring的配置applicationContext.xml
	c.通过spring工厂获取对象  ApplicationContext(ClasspathXmlApplicationContext)
3.spring的bean标签
	id:唯一标识
	class:实现类的路径
	init-method:初始化要调用的方法
	destroy-method:销毁时要调用的方法
	scope:
		singleton:单例
		prototype:多例
4.spring创建对象的3种方式
	1.默认无参构造
	2.工厂类的静态方法
	3.工厂类的动态方法
5.spring的依赖注入
	spring在创建对象的时候,给对象的属性赋值,叫做依赖注入。
	1.有参构造
		<constructor-arg>
         确定属性的
         	name:属性名确定属性
         	index:索引确定属性
         	type:类型确定属性
         确定值的
         	value:基本类型赋值
         	ref:引用类型的赋值
     2.set方式
    	 <property>
     	 name:用来确定属性的。
                name属性的值是set的方法名去掉set后的驼峰命名名字。
          value:基本类型的属性赋值
          ref:引用型类型的属性赋值

例工厂的区别,就是在于单例工厂有一个map集合保存bean对象,
多例没有,创建之后直接返回。
2.spring的工厂类
单例模式下,创建对象的时间节点不一样。
BeanFactory: 顶层接口,什么时候用,什么时候创建对象。
ApplicationContext:BeanFactory的子接口。工厂初始化时创建

掌握的
1.spring的2大核心思想
ioc: 控制反转,对象的创建由我们自己new,换成spring工厂创建
aop: 面向切面的编程,底层就是动态代理,在不修改源码的情况下增强功能
2.spring的入门步骤
a.引入spring-context依赖
b.编写spring的配置applicationContext.xml
c.通过spring工厂获取对象 ApplicationContext(ClasspathXmlApplicationContext)
3.spring的bean标签
id:唯一标识
class:实现类的路径
init-method:初始化要调用的方法
destroy-method:销毁时要调用的方法
scope:
singleton:单例
prototype:多例
4.spring创建对象的3种方式
1.默认无参构造
2.工厂类的静态方法
3.工厂类的动态方法
5.spring的依赖注入
spring在创建对象的时候,给对象的属性赋值,叫做依赖注入。
1.有参构造

确定属性的
name:属性名确定属性
index:索引确定属性
type:类型确定属性
确定值的
value:基本类型赋值
ref:引用类型的赋值
2.set方式

name:用来确定属性的。
name属性的值是set的方法名去掉set后的驼峰命名名字。
value:基本类型的属性赋值
ref:引用型类型的属性赋值


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值