SSM框架--Spring---ioc(控制反转)&di(依赖注入)

Spring

核心技术点: ioc   di  aop  声明式事务 

ioc的底层实现(理解)

spring提供的ioc技术帮助我们解决了程序的高耦合问题,让我们不再花费时间去关心程序的高耦合

  • 耦合关系

耦合:在编程语言中,就是计算机代码之间的依赖关系

代码之间的依赖关系如果很高就意味着程序高耦合,不利于后期项目的扩展开发,因此我们需要给程序松耦合

高耦合—松耦合–低耦合

需求 :自定义ioc的代码,实现更加松耦合的程序

代码实现:

  1. webTest
public class webTest {

    @Test
    public void test2() throws Exception {

        UserService userService1= (UserService) Factory2.getBean("userService");
        System.out.println(userService1);
    }
}
  1. 单例工厂
package cn.itcast.utils;

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

//单例工厂模式
public class Factory2 {

        private static ResourceBundle bundle=null;
        private static Map<String,Object> map=new HashMap();
    static {

        try {

            //反射创建对象
            //只要加载后缀名为properties的文件 统一用ResourceBundle 不能加载xml 底层写死了后缀名
            bundle=ResourceBundle.getBundle("bean");
            //获取所有的key
            Enumeration<String> keys = bundle.getKeys();
            while (keys.hasMoreElements()){
                //获取key  aaa
                String key = keys.nextElement();
                //cn.itcast.service.impl.UserServiceImpl--对象
                String value = bundle.getString(key);
                Class clazz = Class.forName(value);
                Object obj = clazz.newInstance();
                map.put(key,obj);

            }


        }catch (Exception e){
            e.printStackTrace();
        }

    }
    public static Object getBean(String id) throws Exception {

        Object obj = map.get(id);
        return obj;
    }
}

4)多例工厂

package cn.itcast.utils;

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

//多例工厂模式
public class Factory {

        private static ResourceBundle bundle=null;
        private static Map<String,Object> map=new HashMap();
    static {
        //反射创建对象
        //只要加载后缀名为properties的文件 统一用ResourceBundle  不能加载xml 底层写死了后缀名
        bundle=ResourceBundle.getBundle("bean");
        //获取所有的key
        Enumeration<String> keys = bundle.getKeys();
        while (keys.hasMoreElements()){
            //获取key  aaa
            String key = keys.nextElement();
            //cn.itcast.service.impl.UserServiceImpl
            String value = bundle.getString(key);
            map.put(key,value);
        }

    }
    public static Object getBean(String id) throws Exception {

        String value =(String) map.get(id);
        Class clazz = Class.forName(value);
        Object obj = clazz.newInstance();
        return obj;
    }
}

5)UserService

public interface UserService {
    
}
  1. UserServiceImpl
public class UserServiceImpl implements UserService {
   
}
  1. application.xml
<beans>
    <bean id="userService" class="cn.itcast.serviceImpl.UserServiceImpl"></bean>
</beans>

结论

通过以上的配置文件+反射+工厂的方式可以实现程序解耦合,而spring的底层封装的就类似这一套的实现(ioc)

一 认识Spring的ioc容器

ioc:控制反转

指的是对象的控制权由原来开发者在类中自己手动创建控制 反转到 由Spring/ioc容器创建控制
其实spirng底层已经做好了工厂,这个工厂就已经帮助我们创建好了对象,放入到ioc容器中(就是map集合)

ioc作用

帮助咱们创建管理对象,做到程序之间的解耦合

获取对象方式:

传统方式获取对象:主动出击 new
Spring方式获取对象:问ioc容器要对象 

二 Spring概述【了解】

Spring是分层的 Java SE/EE应用 full-stack 开源框架。以 IOC(Inverse Of Control:控制反转)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。

简单说:spring为三层开发提供了一站式的解决方案
web层: servlet---->springMvc框架
service层:声明式事务 --->事务
dao层:jdbc---->jdbcTemplate  (企业多用mybits)
友情提示 spring课程的学习侧重点:ioc技术(DI)  aop技术  声明式事务技术

spring的体系结构图
在这里插入图片描述

三 Spring的ioc快速入门【重点】

环境搭建

1 导入依赖
	  spring坐标依赖  要求junit4.12及以上版本

2 将对象的创建和管理交给spring容器
	  xml配置文件	
3 从spring容器中获取对象
	  java代码的API调用

1)spring的依赖

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

在这里插入图片描述

  1. Demo2
public class Demo2 {

    public static void main(String[] args) {
        // 创建ioc容器管理对象
        ApplicationContext context=new ClassPathXmlApplicationContext("application.xml");
        // 问ioc容器要对象
        UserService userService =(UserService)context.getBean("userService");
        userService.save();
    }
}
  1. application.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">


    <!--
        id:唯一标识名(整个xml下唯一)
        class:类的全限定名
    -->
    <bean id="userService" class="cn.itcast.serviceImpl.UserServiceImpl"></bean>
</beans>

流程图

在这里插入图片描述

四 Spring相关API【理解】

实现类
在这里插入图片描述
在这里插入图片描述

* FileSystemXmlApplicationContext【了解】
	功能:从指定磁盘目录加载xml配置文件,创建spring的ioc容器

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

* ClassPathXmlApplicationContext (加载配置文件的)
	功能:从类路径下加载xml配置文件,创建spring的ioc容器
	
* AnnotationConfigApplicationContext (加载注解的)
	功能:加载注解配置类,创建spring的ioc容器

方法

1. public Object getBean(String id) throws BeansException; (掌握)
	功能:通过指定id获取对象的实例,需要手动强转

2. public <T> T getBean(Class<T> requiredType);
	功能:通过指定类型获取对象的实例,不需要强转
	注意:同一个类型下只能有一个对象实例

五 Spring配置文件【重点】

5.1 Bean标签

配置信息
bean标签:指定创建对象的
	id属性:唯一标识(配置文件中唯一)
	class属性:实现类的全限定名
    scope属性:范围
	 	取值:singleton(单例默认) prototype(多例) 扩展:request,session,globesession..
	   		 singleton:对象是随着容器的创建而创建 随着容器的销毁而销毁 自始至终只有一个对象
			 prototype:对象的创建和销毁与容器的创建和销毁无关 
					   每次执行getBean的时候创建新的对象 调用一次创建一次
					   销毁是会等待垃圾回收机制自动完成的
   init-method属性: 对象创建之后指定调用方法
   destroy-method属性:对象销毁后指定调用方法

5.2 spring创建对象实例三种方式

1.构造方式(重要)
2.静态工厂: 该工厂中获取对象的方法是静态的 可以类名直接调用(了解)
3.实例化工厂:该工厂中获取对象的方法是非静态的 必须得有工厂对象才能调用方法(了解)
1)构造方法实例化【重点】
<!--
        构造方法实例化
			底层使用的是构造器创建对象
    -->
 <bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl"></bean>
2)工厂静态方法实例化【了解】
/**
 * 工厂静态方法实例化
 */
public class Factory {
    public static Object getBean(){
        return new UserServiceImpl();
    }
}
<!--
        工厂静态方法实例化

        class="cn.itcast.utils.Factory" 工厂全限定类名
        factory-method="getBean" 创建userService对象的静态方法

    -->
<bean id="userService" class="cn.itcast.utils.Factory" factory-method="getBean"></bean></bean>
3)工厂普通方法实例化【了解】
/**
 * 工厂普通方法实例化
 */
public class Factory2 {

    public  Object getBean(){
        return new UserServiceImpl();
    }
}
<!--
        工厂普通方法实例化
            先实例化工厂
               <bean id="factory" class="cn.itcast.utils.Factory2"></bean>
            再调用方法创建userService对象
                 <bean id="userService" factory-bean="factory" factory-method="getBean"></bean>
                
				factory-bean="factory" 告诉spring容器从哪个工厂来创建实例
    -->
<bean id="factory" class="cn.itcast.utils.Factory2"></bean>
<bean id="userService" factory-bean="factory" factory-method="getBean"></bean>

六 Bean依赖注入概述(掌握)

依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。

​ 在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是对象的属性应该如何管理,这里spring

提供了技术:依赖注入

依赖注入:对存在依赖关系的属性或者对象自动赋值
属性分类:
	注入简单数据类型的数据
	注入复杂类型的数据(单列(array,list,set)和 双列(map,properties对象))
	注入被spring容器管理的对象

依赖注入的两种方式:构造方法注入和set方法注入 

Bean依赖注入方式

1)构造方法注入(了解)
public class UserServiceImpl implements UserService {

    /*
    * spring除了提供了ioc容器用来创建管理对象
    * 也提供了一个技术可以用来给对象的各种属性赋值:依赖注入(DI)
    *    对象的属性:
    *           简单属性:string interger double...(了解)
    *           对象属性:userDao(掌握)
    *           复杂属性: 数组  list set  单列 |  map properties 双列(掌握)
    *    依赖注入(di):构造器方式赋值(了解)   set属性方式赋值(掌握--用它)
    *
    * */
    
  
  	// 简单属性
    private String name;
    private Integer age;
    // 构造器方式
    public UserServiceImpl(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public void save() {
        System.out.println(name+":"+age);
    }
  
  	
  	// 对象属性
    private UserDao userDao;
    // 构造器方式
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
    public void save() {
        userDao.save();
    }
}
 <!-- dao -->
<bean id="userDao" class="cn.itcast.daoimpl.UserDaoImpl"></bean>
 <!--service -->
<bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl">

        <!--构造器的属性赋值
                constructor-arg标签
                属性:
                    index:数组角标的方式定位属性
                    name:  属性名的方式定位属性
                    type: 属性的全限定名类型定位属性
                        *****以上三种是用来定位属性的
                    value: 给简单数据赋值的
                    ref: 给对象属性进行赋值的(条件:对象值必须也是有ioc容器管理的)
                        *****以上二种是用来给属性赋值的

        -->
        <!--
         构造器简单属性赋值方式:
        <constructor-arg index="0" value="jack"></constructor-arg>
        <constructor-arg index="1" value="18"></constructor-arg>-->
        <!--<constructor-arg name="name" value="jack"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>-->
        <!--<constructor-arg type="java.lang.String" value="jack"></constructor-arg>
        <constructor-arg type="java.lang.Integer" value="18"></constructor-arg>-->

        <!--构造器对象属性赋值
                ref:指向的是被spring容器管理bean的id     
        -->
  	   <constructor-arg name="userDao" ref="userDao"></constructor-arg>
2)set方法注入【重点】
public class UserServiceImpl implements UserService {

    /*
    * spring除了提供了ioc容器用来创建管理对象
    * 也提供了一个技术可以用来给对象的各种属性赋值:依赖注入(DI)
    *    对象的属性:
    *           简单属性:string interger double...
    *           对象属性:userDao
    *           复杂属性: 数组  list set  单列 |  map properties 双列
    *    依赖注入(di):构造器方式赋值(了解)   set属性方式赋值(掌握--用它)
    *
    * */
	/*set方式注入--简单类型*/
    private String name;
    private Integer age;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public void save() {
        System.out.println(name+":"+age);
    }
    
    /*set方式注入--对象类型*/
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void save() {
        userDao.save();
    }
    
    /*set方式注入--复杂单列类型*/
    private Set<Object> arr;
    public void setArr(Set<Object> arr) {
        this.arr = arr;
    }
    @Override
    public void save() {
        System.out.println(arr);
    }
    
    
    /*set方式注入--复杂双列类型*/
    private Properties properties;
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    @Override
    public void save() {
        System.out.println(properties);
    }
    
    /*set方式注入--复杂双列类型*/
    private Map<String,Object> map;
    public void setMap(Map<String, Object> map) {
        this.map = map;
    }
    @Override
    public void save() {
        System.out.println(map);
    }
    
}

 <!-- dao -->
<bean id="userDao" class="cn.itcast.daoimpl.UserDaoImpl"></bean>
 <!--service -->
<bean id="userService" class="cn.itcast.serviceimpl.UserServiceImpl">
<!--set属性注入方式
                property
                   name属性:按照set后面的值来定位属性的(首字母小写)
                   value属性:给简单类型赋值
                   ref属性:给对象属性进行赋值的(条件:对象值必须也是有ioc容器管理的)
        -->
        <!--简单属性-->
        <property name="name" value="jack"></property>
        <property name="age" value="18"></property>

        <!--对象属性-->
        <property name="userDao" ref="userDao"></property>

        <!--复杂属性 单列
            数组  list  set
               三组搭配随意用: <array>  <list>  <set>
        -->
        <property name="arr">
            <set>
                <value>abc</value> 
                <ref bean="userDao"></ref> 
            </set>
        </property>

        <!--复杂属性 多列-->
        <property name="map">
            <map>
                <entry key="key1" value="abcd"></entry>
                <entry key="key2" value-ref="userDao"></entry>
            </map>
        </property>

        <property name="properties">
            <props>
                <prop key="username">root</prop>
                <prop key="password">root</prop>
            </props>
        </property>
</bean>  

七、Spring注解开发

​ Spring是轻代码而重配置的框架,配置比较繁重,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。

spring的开发方式:

1 全xml方式
	  特点:所有配置都在xml配置文件中


2 半xml半注解方式
      特点:一半使用的是配置文件(第三方)  一半使用的是注解(自己的资源)


3 全注解方式
      特点:所有配置全部用注解
      spring--全注解(半成品(理解))--springboot(成品 企业开发趋势)--项目一,二


案例:使用spring操作account表做添加(全xml方式    半xml半注解方式    全注解方式)

1.1 spring的半xml和半注解式开发

半xml半注解式:一般我们会将自己的资源用注解代替 第三方资源继续保留XML方式
条件:spring的注解默认是关闭的 需要在xml中配置一个注解扫描器开启注解
开启注解扫描器:<context:component-scan base-package="cn.itcast"></context:component-scan>
注解扫描器的作用:告诉spring去哪些包(包含子包)下解析编写好的注解

使用到的注解概述

ioc:控制反转(将对象交给spring创建管理)

@Component
	@Controller
	@Service
	@Repository
特点:被扫描到后,后将被自己注解的类创建对象 放在ioc容器中	
1.需要配置到类上
2.默认不配置标识该对象在spring容器中的唯一标识:就当前类名首字母小写
3.如果配置标识:可以用value指定唯一标识

DI:依赖注入(为spring管理的对象进行属性赋值)

@Autowired
	spring默认按照接口类型从容器中查找对象并注入 set属性可以省略不写
@Qualifier
	取值 Value:用来指定唯一标识
		按照指定的唯一标识从容器中查找对象并注入
	特点:没办法单独使用 只能依附@Autowired一起出现	
    
总结:
1 如果ioc中只有一个实现对象,就直接@Autowired
2 如果ioc容器中有多个实现对象,可以使用方式:
				  @Autowired+@Qualifier(指定id标识) (掌握)

了解:不用
JDK提供的依赖注入的注解 
@Resource:按照唯一标识从容器中查找对象并注入
	取值 Name:用来指定唯一标识
相当于@Autowired+@Qualifier        

生命周期的注解(了解)

@Scope : 对象的作用域	 配置在类上						
	Value属性(singleton|  prototype)
@PostConstruct : 配置到方法上  init-method
	 配置初始化方法
@PreDestory:配置到方法上      destroy-method
	 配置销毁方法

半xml半注解的执行流程
在这里插入图片描述

1.2 spring的全注解式开发(理解)

全注解:自己编写的资源和第三方的资源都用注解方式
ps:该spring的全注解不是最终版 所以很麻烦 等到springboot在该基础做完优化 就是最终版了
条件:
1 使用配置类替换xml配置文件
		创建一个类,使用注解申明是一个配置类
2 代码端不在加载配置文件,而是加载配置类
		 ApplicationContext context=new AnnotationConfigApplicationContext(配置类.class);

使用到的注解

@Configuration:声明配置类 可以省略不写

@ComponentScan: 开启包扫描
		取值 basePackages:指定扫描的包

@PropertySource:将properties配置文件交给spring容器管理
		取值 value:指定要加载的文件地址

@Bean : 配置到方法上,表明此方法的返回值交给spring容器管理
	   将第三方对象交给spring容器管理的时候使用@Bean
	   取值 value:指定在ioc容器中的id标识
      
@Value:用来取properties中的内容 但是只能设置在成员变量上 类似el表达式获取数据 ${jdbc.username}   

@Import(从配置类的.class):引入从配置类

全注解的执行流程图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值