Spring5第一节(了解Spring5)

引言

EJB(Enterprise Java Bean)存在的问题:EJB 是重量级的框架。

	1.运行环境苛刻
	2.代码移植性差

什么是spring?

Spring是一个轻量级的JavaEE解决方案,整合众多优秀的设计模式
  • 轻量级
1.对于运行环境是没用额外要求的
	开源 tomcat	resion	jetty
	收费 weblogic	websphere
2.代码移植性高
	不需要实现额外接口
  • JaveEE解决方案
    在这里插入图片描述

  • 整合设计模式

1.工厂
2.代理
3.模块
4.策略
  • 什么是设计模式
1.广义概率
   面向对象设计中,解决特定问题的经典代码
2.狭义概念
   GOF4人帮定义的23种设计模式:工厂,适配器,装饰器门面,代理,模块......

工厂设计模式

什么是工厂设计模式?

1.概念: 通过工厂雷,创建对象
		User user=new User();
		UserDao userDAO=new UserDAOImpl();
2.好处:解耦合
		耦合:指定是代码间的强关联关系,一方的改变会影响到另一方
		问题:不利于代码维护
		简单:把接口的实现类,硬编码在程序中(耦合)
			UserService userService=new UserServiceImpl();	

简单工厂的设计

package com.xianxain.day01;

import java.io.*;
import java.util.Properties;

//工厂类
public class BeanFactory {
    //创建properties集合
    private static Properties env=new Properties();
    private static Class classz= null;
    static {
//        //第一步  获取IO输入流
//        File file = new File("src/main/resources/appcontext.properties");
//        InputStream in = new FileInputStream(file); 或者以下操作
        InputStream resourceAsStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
        try {
            //第二步  文件内容 封装 Properties集合中 Key=userService value=com.xianxain.day01.UserServiceImpl
            env.load(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                //关闭流
                resourceAsStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 工厂方法
     * @return
     * 对象的创建方式:
     *          1.直接调用构造器 创建对象 UserService = new UserServiceImpl()
     *          2.通过反射的形式 创建对象  解耦合
     *                  Class classz=Class.forName("com.xianxian.day01.UserServiceImpl")
     *                  UserService userService=(UserService)classz.newInstance();
     */
    public static UserService getUserService(){
        //但这种方式还是有耦合  所以通过反射
        //        return new UserServiceImpl();
//        反射
//        Class classz= null;
//        UserService userService=null;
//        try {
//            classz = Class.forName("com.xianxian.day01.UserServiceImpl");
//            userService=(UserService) classz.newInstance();
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        } catch (InstantiationException e) {
//            e.printStackTrace();
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        }
        UserService userService=null;
        try {
        	//通过Properties的key获取value
            classz = Class.forName(env.getProperty("userService"));
            userService=(UserService) classz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userService;
    }
    public static UserDao getUserDao(){

        UserDao userDao=null;
        try {
            classz =Class.forName(env.getProperty("userDao"));
            userDao=(UserDao)classz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return userDao;
    }
}
  • 配置文件applicationContext.properties
# Properties 集合 存储 Properties文件的内容
#特殊Map key=String  value=String
#Properties [UserService=com.xianxain.day01.UserServiceImpl]
#Properties.getProperty("userService")

userService=com.xianxain.day01.UserServiceImpl

#userService=com.xianxain.day01.UserServiceImplNew

userDao=com.xianxain.day01.UserDAOImpl

通用工厂的设计

问题:简单工厂会存在大量的代码冗余
在这里插入图片描述

解决方案:通用工厂的代码:

//工厂类
public class BeanFactory {
	//创建properties集合
    private static Properties env=new Properties();
	private static Class classz= null;

     /**
     * 通用工厂
     * @param key  根据传入的对象 读取对应的配置文件中key的值
     * @return 进行返回
     */
    public static Object getBean(String key){
        Object object=null;
        try {
            classz=Class.forName(env.getProperty(key));
            object=classz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return object;
    }
}
通过工厂的使用方式
1.定义类型(类)
2.通过配置文件的配置告知工厂(applicationContext.properties)
	key=value
3.通过工厂获得类的对象
	Object ret=BeanFactory.getBean("key")

总结

Spring本质: 工厂模式 为我们提供的工厂叫做ApplicationContext 以及配置文件:applicationContext.xml

第一个Spring小程序

环境搭建

依赖查询网站:https://mvnrepository.com/

配置Spring的jar包

#  在pom文件里面引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.9</version>
</dependency>

Spring的配置文件

	1.配置文件的放置位置: 任意位置 没有硬性要求
	2.配置文件的命名		:没有硬性要求  但建议:applicationContext.xml
注意:应用Spring框架时,需要进行配置文件路径的设置

在这里插入图片描述

Spring的核心API

  • ApplicationContext
作用:Spring提供的ApplicationContext这个工厂,用于对象的创建
好处: 解耦合
  • ApplicationContext接口类型
    接口:屏蔽实现的差异
    非web环境 : ClassPathXmlApplicationContext例如:(main junit)
    web环境 : XmlWebApplicationContext

在这里插入图片描述
为什么没有XmlWebApplicationContext?因为没有引入web还需要引入web
web依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

点击刷新.就出现了

在这里插入图片描述重量级资源

ApplicationContext工厂的对象占用大量内存
不会频繁的创建对象 : 一个应用只会创建一个工厂对象
ApplicationContext工厂:一定是线程安全的(多线程并发访问)

程序的开发

1.创建类型
2.配置文件的配置 applicationContext.xm

<bean id="id名称(要唯一性)" class="文件的全限定名"/>

3.通过工厂 获得对象
ApplicationContext (因为是单元测试所以用非web环境)
|- ClassPathXmlApplicationContext |
第一种方式:

ApplicationContext ctx=new ClassPathXmlApplicationContext("配置文件的路径")
类型  名称=(类型)ctx.getBean("对应的Bean的id")

第二种方式(传入多个配置文件):

ApplicationContext ctx=new ClassPathXmlApplicationContext("配置文件的路径1","配件文件的路径2"......)

第三种方式(传入一个数组)

ApplicationContext ctx=new ClassPathXmlApplicationContext(new String[]
{"配置文件的路径1","配置文件的路径2",.....})

细节分析

名称解析

Spring工厂创建的对象,叫做Bean或者组件(componet)

Spring工厂的相关的方法

@Test
public void text4{
	ApplicationContext ctx=new ClassPathXmlApplicationContext("/applicationContext.xml");
	//第一种getBean的重载
	//类型  	名称=(类型)ctx.getBean("对应的Bean的id");
	Person person = (Person)ac.getBean("person");
	//第二种getBean的重载 这种可以避免强制类型转换
	//类型 	名称=ctx.getBean("对应的Bean的id",对应类.class);
	Person person1 = ac.getBean("person", Person.class);
	//第三种getBean重载  需要注意的是:这种只能 配置文件中只有一个Bean 否则异常 (当前Spring的配置文件中,只能只有一个<bean class是唯一的 否则异常)
	//类型	名称=ctx.getBean(对应类.Class);
	Person bean = ac.getBean(Person.class);
	//获取当前Spring配置文件中所有Bean标签(Bean定义)的id的值 返回的对象是一个String数组 
	String[] beanDefinitionNames=ctx.getBeanDefinitionName();
	//进行遍历
	for(String beanDefinitionName: beanDefinitionNames){
			System.out.println("beanDeinitionName"+beanDeinitionName);
	}
	//根据指定的类型获取Spring配置文件中对应的Bean的名字(id的值)
	String[] beanNameForTypes=ctx.getBeanNameForType(类型.class);
	//进行遍历
	for(String beanNameForType:beanNameForTypes){
			System.out.println("beanNameForType"+beanNameForType);
	}
	//用于判断是否存在指定id值的Bean  返回的是boolean值  需要注意的是:只能判断id值 不能判断name值
	if(ctx.contaibsBeanDefinition("id的值")){
			System.out.println("True = "+true)
	}else{
			System.out.println("False = "+false)
	}

	//用于判断是否存在指定id值的Bean  返回的是boolean值 需要注意的是:id值和name值都是可以判断的
	if(ctx.containsBean("id的值")){
			System.out.println("True = "+true);
	}else{
			System.out.println("False = "+false)
	}
}

配置文件中需要注意的细节

1.只配置class属性
<bean class="类的全限定名"/>
	//1.上述这种配置 有没有 id 值 ?
			//可以通过以上相关方法中获取id的值的方法进行获取
			//可以得到一个"类全限定名#0"
	//2.应用场景:如果这个bean只要用一次,那么就可以省略id值,
			//反之如果这个bean使用多次或者被其他bean应用需要设置id值
2.name属性
作用:用于在Spring的配置文件中,为bean对象定义别名(小名)
相同的地方
			1.ctx.getBean("id的值/name的值");//--->object
			2.  <bean id=""  class=""
				等效于
				<bean name="" class=""
区别:
			1.别名可以定义多个(以逗号分隔),但是id属性只能有一个值
			<bean id="名称" name="名称1,名称2,名称3"  class=""/>
			2.XML的id属性的值,命名要求,必须要以字母开头,字母,数字,下划线,连字符 注意:不能以特殊字符开头 
						name属性的值,命名没有任何的要求
							所以name属性会应用在特殊命名的场景下:
						XML发展到了现在:ID属性的限制,不存在了  也可以反斜线命名了
			3.代码区别
			//用于判断是否存在指定id值的Bean  返回的是boolean值  需要注意的是:只能判断id值 不能判断name值
			if(ctx.contaibsBeanDefinition("id的值")){
					System.out.println("True = "+true)
			}else{
					System.out.println("False = "+false)
			}

			//用于判断是否存在指定id值的Bean  返回的是boolean值 需要注意的是:id值和name值都是可以判断的
			if(ctx.containsBean("id的值")){
					System.out.println("True = "+true);
			}else{
					System.out.println("False = "+false)
			}
			
		


Spring工厂的底层实现原理(简易版)

在这里插入图片描述

思考

问题: 未来在开发过程中, 是不是所有的对象,都交给Spring工厂创建呢?
回答:理论上 是的,但是有特列 : 实体对象(entity)是不会交给Spring创建, 它是持久层框架进行创建(例如:Mybatis)

Spring5.x与日志框架的整合

Spring与日志框架进行整合,日志框架就可以在控制台中,输出Spring框架运行过程中的一些重要的信息
好处:便于了解Spring框架的运行过程,利于程序的调试

Spring如何整合日志框架

默认
Spring1.2.3早期都是于commons-loggin.jar
Spring5.x默认整合的日志框架 logback log4j2

Spring5.x整合log4j
1.引入log4j jar包
2.引入log4.properties配置文件

  • 在pom文件中引入依赖
   <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>2.0.0-alpha1</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/log4j/log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
  • log4j.properties
#resources 文件夹目录下
### 配置根
log4j.rootLogger = debug,console
### 日志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd H:mm:ss} %-5p %c{1}:%L- %m%n

测试
在这里插入图片描述

这样就表示成功了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值