zoukankan      html  css  js  c++  java
  • Spring从入门到精通

    第一章 Spring基础

    1.环境搭建

    导入Pom

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

    附属下载的内容
    在这里插入图片描述

    2. 配置文件

    1、配置文件的放置位置:任意位置即可。
    2、配置文件的命名:没有硬性要求,建议为applicationContext.xml

    注意在以后的编码过程中,需要对配置文件路径进行设置

    2.1.配置文件创建

    在这里插入图片描述

    3. Spring的核心API

    3.1 applicationContext

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

    非web环境在这里插入图片描述
    在这里插入图片描述

    3.2 applicationContext

    ApplicationContext工厂的对象占用大量的内存
    不会频繁创建对象,一个应用之后创建一个工厂对象。
    applicationContext这种工厂一定是线程安全的。
    

    4.Spring第一个程序

    步骤:

    1、创建类型
    
    2、配置文件的配置 applicationContext.xml
    
       <!--id起个名字,唯一;class配置全限定名-->
        <bean id="person" class="com.xiaohe.Person"></bean>
    

    3、通过工厂类,获取对象

        @Test
        public void test(){
            //获取Spring工厂
            /**
             * ClassPathXmlApplicationContext参数表示配置文件的路径
             * */
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("/applicationContext.xml");
    
            //根据工厂获取对象
            /**
             * getBean参数表示配置文件bean下的id名字
             * */
            Person person = (Person) applicationContext.getBean("person");
            System.out.println(person);
        }
    
    }
    

    细节分析

    • 名称解释

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

    • spring工厂相关的方法
     @Test
        public void test1(){
            ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
            //Person person=applicationContext.getBean("person",Person.class);
            //System.out.println(person);
    
            //当前Spring配置文件中,只能有一个<bean class是Person类型>
           Person person=applicationContext.getBean(Person.class);
            System.out.println(person);
    
           //获取的是Spring工厂配置文件所有配置的ID值
           String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
            for (String beanDefinitionName : beanDefinitionNames) {
                System.out.println("beanDefinitionNames="+beanDefinitionName);
            }
    
          //根据类型获取spring工厂配置文件的id值
         String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
            for (String s : beanNamesForType) {
                System.out.println("--->"+s);
            }
    
           //用于判断配置文件是否存在指定id值的bean
           boolean isExist = applicationContext.containsBeanDefinition("person");
            System.out.println(isExist);
          
            //用于判断配置文件是否存在指定id值的bean
            boolean isExist= applicationContext.containsBean("person");
            System.out.println(isExist);
          
        }
    

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

    在spring配置文件中只写class,不写id

      <bean class="com.xiaohe.Person"/>
    

    测试

    @Test
      public void test2(){
          //创建ApplicationContext对象
          ApplicationContext applicationContext=new ClassPathXmlApplicationContext("/applicationContext.xml");
          /*Person bean = applicationContext.getBean(Person.class);
          System.out.println("--->"+bean);*/
          String[] beans = applicationContext.getBeanDefinitionNames();
          for (String bean : beans) {
              System.out.println("----》"+bean);
          }
    
      }
    

    结果
    在这里插入图片描述

    Spring配置文件的name属性

    作用:用于在spring的配置文件中,为bean对象定义别名
    id与name(别名)的相同点与不同点
    相同:
    1、applicationContext.getBean(“id/name”);
    2、<bean name="" class="" 等效于<bean name="" class=""
    不同:
    1、别名可以定义多个,中间用逗号隔开
    2、xml 的id属性值命名时要求:必须要以id开头,name属性的值,命名没有要求。

    5.spring工厂的底层原理(简易版)

    在这里插入图片描述

    第二章 spring与日志框架的整合

    spring与日志框架的整合,日志可以在控制台进行打印,输出一些重要的信息。
    默认:spring默认整合logback,log4j2

    Spring整合log4j过程
    1、引入log4j jar包
    2、引入log4j.properties配置文件

    • 引入pom文件
     <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    
    • log4j.properties
    # resources # 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-ddHH:mm:ss} %-5p %c{1}:%L - %m%n
    

    第三章 注入

    1.什么是注入

    通过Spring工厂及配置文件,为所创建的对象的成员变量赋值。

    1.1为什么要注入

    在这里插入图片描述

    1.2如何进行注入

    • 1.类为成员变量提供set/get方法
    • 2.配置spring的配置文件
      <bean id="person" name="p" class="com.xiaohe.Person" >
            <property name="name">
                <value>和振斌</value>
            </property>
            <property name="age">
            <value>20</value>
            </property>
        </bean>
    
    • 测试
      /**
       * 测试注入
       * */
      @Test
      public void test5(){
          ApplicationContext applicationContext=new ClassPathXmlApplicationContext("/applicationContext.xml");
          Person person = (Person) applicationContext.getBean("person");
          System.out.println("person:"+person);
      }
    

    1.3注入的好处

    解耦合

    1.4Spring注入原理分析(简易版)

    在这里插入图片描述
    Set注入和构造注入
    在这里插入图片描述

    第三章 控制反转与依赖注入

    1、控制反转(IOC)

    1、控制:对于成员变量赋值的控制权
    2、反转控制:把对于成员变量赋值的控制权,从代码中反转到spring工厂和配置文件中去。
    3、底层实现:工厂设计模式

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

    依赖注入(Dependency Injection DI)

    注入:通过Spring的工厂及其配置文件,为对象的成员变量赋值

    依赖注入:当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以把另一个类作为本类的成员变量,最终通过Spring配置文件进行注入
    好处:解构

    在这里插入图片描述
    在这里插入图片描述

    2、Spring工厂创建复杂对象的三种方式

    步骤

    • 1、实现FactoryBean接口
      在这里插入图片描述
    public class ConnectionFactory implements FactoryBean<Connection> {
        //用于书写创建复杂对象的代码
        public Connection getObject() throws Exception {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
    
            return conn;
        }
    
        public Class<?> getObjectType() {
            return Connection.class;
        }
    
        public boolean isSingleton() {
            return false;
        }
    }
    
    • 2、Spring配置文件的配置
    <bean id="conn" class="com.xiaohe.factoryBean.ConnectionFactory"/>
    

    2.2、实例工厂

    1、避免spring的侵入
    2、整合遗留问题
    

    开发步骤

    <bean id="connFactory"class="com.baizhiedu.factorybean.ConnectionFactory"></bean>
    <bean id="conn" factorybean="connFactory"factorymethod="getConnection"/>
    

    实例工厂

        <bean id="conn" class="com.xiaohe.factoryBean.ConnectionFactory" factory-method="getConnection"/>
    

    1.3Spring工厂总结

    在这里插入图片描述

    第四章 控制Spring工厂创建对象的次数

    1、简单工厂创建次数

    <bean id="accont" scope="singleton | prototype" class="xxx.Account"
    singleton:只创建一次
    prototype:创建多次
    

    2、为什么要控制对象的创建次数
    好处:节省内存

    生命周期

    在这里插入图片描述

    第五章 后置处理Bean

    1、BeanPostProcessor作用:对于Spring工厂所创建的对象,进行再加工
    在这里插入图片描述

    我们实现BeanPostProcessor规定的接口的方法
    Object postProcessBeforeInitiallization(Object bean,String beanName)
    作用:Spring在创建完对象,并进行注入后,可以运行Before方法进行加工
    获得Spring创建好的对象,通过方法的参数
    最终通过返回值交给Spring框架
    
    
    Object postProcessAfterInitallization(Object bean,Strinng beanName)
    作用:Spring在执行完对象的初始化操作后,可以运行After方法进行加工
    获得Spring创建好的对象,通过方法的参数
    最终通过返回值交给Spring框架
    
    • BeanPostProcessor开发步骤
      1、类实现BeanPostProcessor接口
      public class MyBeanPostProcessor implements BeanPostProcessor {
      
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("实现了postProcessBeforeInitialization");
            return bean;
        }
      
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
             Categroy categroy= (Categroy) bean;
             categroy.setName("hzb cool");
            return categroy;
        }
      
      • spring配置文件配置
            <bean id="c" class="com.xiaohe.BeanPost.Categroy">
                <property name="id" value="10"/>
                <property name="name" value="hzb"/>
            </bean>
    
        <bean id="myBeanPostProcessor" class="com.xiaohe.BeanPost.MyBeanPostProcessor"/>
    

    运行效果
    在这里插入图片描述

    • 注意BeanPostProcessor会对工厂所有对象进行加工。

    第六章 AOP编程

    1、静态代理设计模式

    为什么需要代理设计模式?
    

    在这里插入图片描述

    2、代理设计模式

    2.1 概念

    通过代理类,为原始类增加额外的功能
    好处:利于原始类的维护
    

    2.2 编码

    静态代理:为每一个原始类,手工编写一个类

    public class UserServiceProxy implements UserService {
        //原始对象
        private UserServiceImpl userService=new UserServiceImpl();
        public void register(User user) {
            System.out.println("日志的额外功能");
            userService.register(user);
        }
    
        public boolean login(String name, String password) {
            System.out.println("日志的额外功能");
            return userService.login(name,password);
        }
    }
    

    2.3 静态代理存在的问题

    1、静态类文件数量过多,不利于项目管理
    UserServiceImpl ----------UserServiceProxy
    OrderServiceImpl---------OrderServiceProxy
    2、额外功能维护性差
    

    3、Spring的动态代理

    3.1 概念

    通过动态代理类为原始类增加额外功能

    3.2搭建环境

    导入pom

    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
    
    
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.5</version>
        </dependency>
    
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
    

    3.3 开发步骤

    1.第一步:创建原始对象

    public class UserServiceImpl implements UserService {
        public void register(User user) {
    
            System.out.println("执行业务运算+DAO");
        }
    
        public boolean login(String name, String password) {
            System.out.println("执行了登录方法");
            return false;
        }
    }
    

    第二步:创建userService对象

    <bean id="userService" class="com.xiaohe.proxy.OrderServiceImpl"/>
    

    额外功能开发 Spring提供了MethodBeforceAdvice接口
    第三步: 额外功能

    public class Before implements MethodBeforeAdvice {
    
        /**
         * 作用: 需要运行在原始方法执行之前运行额外功能,书写在before方法中
         * */
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("----method before advice log");
        }
    }
    
    <bean id="before" class="com.xiaohe.dynamic.Before"/>
    

    第四步:定义切入点

    切入点:额外功能加入的位置
    目的:由程序员根据自己需求,决定额外功能加入给哪个原始方法

    第五步 简单的测试:让所有的文件
    在配置里面写

    <aop:config>
               <!--切入点-->
                <!--expression切入点表达式 表示所有的方法都是切入点-->
               <aop:pointcut id="pc" expression="execution(* *(..))"/>
      </aop:config>
    

    组装

    <!--组装-->
               <aop:advisor advice-ref="before" pointcut-ref="pc"/>
    

    调用

    目的:获取Spring工厂创建的动态代理的对象,并进行调用
    注意
    1、Spring的工厂通过原始对象的id值获得的是代理对象
    ctx.getBean(“userService”);
    2、获得的代理对象后,可以通过声明接口类型,进行对象的存储

    4、动态代理的好处

    好处一、
    在额外功能不改变的过程中,创建其他目标类的对象时,只需要指定原始对象即可。
    在这里插入图片描述
    好处二、
    动态代理额外功能的维护性大大增强。

    5、动态代理详解

    四步骤
    在这里插入图片描述

    5.1、Spring动态代理详解

    • MethodBeforeAdvice分析
      1、MethodBeforeAdvice接口的作用:额外功能运行在原始方法之前,进行额外功能操作。
    public class Before implements MethodBeforeAdvice {
    
        /**
         * 作用: 需要运行在原始方法执行之前运行额外功能,书写在before方法中
         * method表示:额外功能所增加给的那个原始方法
         * Object[]:额外功能增加给那个原始方法的参数
         * Object:原始对象
         * */
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println("----method before advice log");
        }
    }
    

    2、Before方法的三个参数在实战中,该如何使用:
    before方法的参数,在实战中,会根据需要进行使用,不一定都会用到,也可能用不到。

    • MethodInterceptor(方法拦截器)
    /**
     * 拦截器
     * invoke方法的作用:额外功能写在invoke
     *                  额外方法 原始方法之前
     *                           原始方法之后
     *                           原始方法之前 之后
     *   参数:MethodInvocation 表示额外功能所增加的那个原始方法
     * */
    public class Arround implements MethodInterceptor {
    
        public Object invoke(MethodInvocation invocation) throws Throwable {
    
            System.out.println("------前--------");
            //原始方法运行
            Object ret = invocation.proceed();
    
            System.out.println("------后---------");
            return ret;
        }
    }
    

    MethodBeforeAdvice只能运行在原始方法之前

    5.2、切入点详解

    <aop:pointcut id="pc" expression="execution(* *(..))"/>
    

    切入点表达式:
    execution()切入点函数
    * *(…)
    在这里插入图片描述
    第一个 *表示修饰符和返回值
    第二个 *表示方法名
    第三个 …表示参数
    精准方法切入点表示方法
    在这里插入图片描述
    execution()切入点函数

    1、最为重要的切入点函数,功能最全
    2、执行方法切入点表达式类切入点表达式包切入点函数
    
    弊端:书写麻烦
    

    args

    作用:主要用于函数方法参数的匹配
    切入点:方法参数必须是两个字符串类型的参数
    

    within

    主要用于进行类、包切入点表达式的匹配
    切入点:UserServiceImpl这个类
    execution(* *.userServiceImpl.*(..))
    within(*..UserServiceImpl)
    
    
  • 相关阅读:
    web前端之Javascript的输出
    python编码问题
    python面试题1
    机器学习三剑客补充
    JavaScript设计模式与开发实践 组合模式
    JavaScript设计模式与开发实践 命令模式
    JavaScript设计模式与开发实践 发布—订阅模式
    JavaScript设计模式与开发实践 迭代器模式
    JavaScript设计模式与开发实践 代理模式
    JavaScript设计模式与开发实践 策略模式
  • 原文地址:https://www.cnblogs.com/HezhenbinGoGo/p/14243211.html
Copyright © 2011-2022 走看看