JavaEE学习笔记

JavaEE学习笔记

By WHU_LiX 2020
说明:课程笔记,根据黑马程序员的JavaEE视频整理
备忘归档

目录

01 初探spring

程序的耦合

/**
 *程序的耦合
 *      耦合:程序间的依赖关系
 *          包括:
 *              类之间的依赖
 *              方法间的依赖
 *      解耦:降低程序间的依赖关系
 *      实际开发:编译期不依赖,运行时才依赖
 *      解耦的思路:
 *          第一步:使用反射来创建对象,而避免使用"new"关键字
 *          第二步:通过读取配置文件来获取要创建的对象全限定类名
 */

工厂模式解耦

编写工厂类和配置文件(未用spring)
  • 创建一个创建Bean对象的工厂
  • Bean:可重用组件(cs英语)
  • JavaBean:用java语言编写的可重用组件
    • javabean != 实体类,javabean>实体类
/**
 * 一个创建Bean对象的工厂
 * 创建service和dao对象
 * 1.需要一个配置文件来配置我们的service和dao
 *      配置的内容:唯一标识=全限定类名(key-value)
 * 2.通过读取配置文件中配置的内容,反射创建对象
 */
  • 配置文件:xml、properties
package com.itheima.factory;

import java.io.InputStream;
import java.util.Properties;

/**
 * 一个创建Bean对象的工厂
 * 创建service和dao对象
 * 1.需要一个配置文件来配置我们的service和dao
 *      配置的内容:唯一标识=全限定类名(key-value)
 * 2.通过读取配置文件中配置的内容,反射创建对象
 *
 * 配置文件可以是xml也可以是properties(暂时没用到spring),此处用properties
 */
public class BeanFactory {
   
    //读取properties
    //定义一个Properties对象
    private static Properties props;
    //使用静态代码块为Properties对象赋值
    static {
   
        try{
   
            //实例化对象
            props = new Properties();//不能消除耦合,只能降低
            //获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
        }
        catch (Exception e){
   
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }

    /**
     * 根据Bean的名称获取bean对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
   
        Object bean = null;
        try {
   
            String beanPath = props.getProperty(beanName);
            bean = Class.forName(beanPath).newInstance();

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

}

  • 此时存在的问题:

    • 此时创建的类是多例的,执行效率没有单例对象高
  • 解决方法:

    • 定义一个Map,用于存放我们要创建的对象,我们称之为容器
    package com.itheima.factory;
    
    import java.io.InputStream;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    /**
     * 一个创建Bean对象的工厂
     * 创建service和dao对象
     * 1.需要一个配置文件来配置我们的service和dao
     *      配置的内容:唯一标识=全限定类名(key-value)
     * 2.通过读取配置文件中配置的内容,反射创建对象
     *
     * 配置文件可以是xml也可以是properties(暂时没用到spring),此处用properties
     */
    public class BeanFactory {
         
        //读取properties
        //定义一个Properties对象
        private static Properties props;
    
        //定义一个Map,用于存放我们创建的对象,称之为容器
        private static Map<String,Object>beans;
    
        //使用静态代码块为Properties对象赋值
        static {
         
            try{
         
                //实例化对象
                props = new Properties();//不能消除耦合,只能降低
                //获取properties文件的流对象
                InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
                props.load(in);
                //实例化容器
                beans=new HashMap<String, Object>();
                //取出配置文件中所有的key
                Enumeration keys = props.keys();
                //遍历枚举
                while(keys.hasMoreElements()){
         
                    //取出每个key
                    String key = keys.nextElement().toString();
                    //根据key获取value
                    String beanPath = props.getProperty(key);
                    Object value = Class.forName(beanPath).newInstance();
                    //把key和value存入容器中
                    beans.put(key,value);
                }
            }
            catch (Exception e){
         
                throw new ExceptionInInitializerError("初始化properties失败");
            }
        }
    
        /**
         * 根据bean的名称获取对象(单例)
         * @param beanName
         * @return
         */
        public static Object getBean(String beanName){
         
            return beans.get(beanName);
        }
        /**
         * 根据Bean的名称获取bean对象
         * @param beanName
         * @return
    
        public static Object getBean(String beanName){
            Object bean = null;
            try {
                String beanPath = props.getProperty(beanName);
                bean = Class.forName(beanPath).newInstance();
    
            }
            catch (Exception e){
                e.printStackTrace();
            }
            return bean;
        }*/
    
    }
    
    

IoC(inversion of control)控制反转

  • 控制反转:把创建对象的权利交给框架,是框架的重要特征,包括依赖注入和依赖查找

  • 通过工厂模式,将类来查找创建对象的权限交给工厂,控制权发生转移,所以叫控制反转

  • 优点:削减耦合

spring基于xml的IoC

实例
  • maven工程导入dependency:

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.2.9.RELEASE</version>
            </dependency>
    
  • 创建配置文件(bean.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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
        
    </beans>
    
  • 创建bean

        <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
        
        <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
    
  • 获取spring容器

    ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
    
  • 根据id获取bean对象(两种方式:强转类型和函数参数设置)

    IAccountService as = (IAccountService)ac.getBean("accountService");
    IAccountDao adao = ac.getBean("accountDao",IAccountDao.class);
    
applicationContext的3个常用实现类
  1. ClassPathXmlApplicationContext:可以加载类路径下的配置文件,要求配置文件必须在类路径下,不在的话就加载不了。
  2. FIleSystemXmlApplicationContext:加载磁盘任意路径下的配置文件(必须有访问权限)
  3. AnnotationConfiApplicationContext:用于读取注解创建容器
核心容器的两个接口引发出的问题
  • ApplicationContext:
    • 在构建核心容器时,创建对象采取的策略是采用立即加载的方式,即只要一读取完配置文件马上就创建配置文件中的对象
    • 单例对象适用
    • 实际开发中更多采用此接口
  • BeanFactory:
    • 在构建核心容器时,创建对象采取的策略是采用延迟加载的方式,即什么时候根据id获取对象,什么时候才真正创建对象
    • 多例对象适用
spring中bean的细节
  • 创建bean的三种方式

    • 使用默认构造函数创建:在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时,采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
    	<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
    
    • 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象并存入spring容器)
    <bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
    
    • 使用静态工厂中的静态方法创建对象(使用某个类中的静态方法创建对象并存入spring容器)
    <bean id="accountService" class="com.itheima.factory.staticFactory" factory-method="getAccountService"></bean>
    
  • bean对象的作用范围

    • 默认是单例

    • bean标签的scope属性:

      ​ 作用:用于指定bean的作用范围

      ​ 取值:常用前两个

      ​ singleton:单例的(默认值)

      ​ prototype:多例的

      ​ request:作用于web应用的请求范围

      ​ session:作用于web应用的会话范围

      ​ global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境是,它就是session

  • bean对象的生命周期

    • 单例对象

      • 出生:当容器创建时,对象出生
      • 活着:只要容器还在,对象一直生存
      • 死亡:容器销毁,对象消亡

      单例对象的生命周期和容器相同

    • 多例对象

      • 出生:当使用对象时,spring框架为我们创建
      • 活着:对象只要是在使用过程中就一直活着
      • 死亡:当对象长时间不用,且没有别的对象引用时,由java的垃圾回收器回收

spring中的依赖注入

依赖注入Dependency Injection
  • IoC的作用:

    ​ 降低程序间的耦合(依赖关系)

  • 依赖关系的管理:都交给spring来维护,依赖关系即在当前类中需要用到其他类的对象,由spring来为我们提供,我们只需要在配置文件中说明

  • 依赖关系的维护 即 依赖注入

  • 依赖注入:

    能注入的数据:三类

    1. 基本类型和String
    2. 其他的bean类型(在配置文件中或者注解配置过的bean)
    3. 复杂类型/集合类型

    注入的方式:三种

    1. 使用构造函数提供

      • 使用标签:constructor-arg 出现位置:bean标签内部

      • 标签中的属性:

        type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些函数的原型

        index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置是从0开始

        name:用于指定给构造函数中指定名称的参数赋值(常用)

        -----------------------以上三个用于指定给构造函数中哪个参数赋值-------------------------------------------

        value:用于提供基本类型和String类型的数据

        ref:用于指定其他的bean类型的数据,它指的就是在spring的IoC核心容器中出现过的bean对象

      • 优势:

        在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。

      • 弊端:改变了bean对象的实例化方式,使我们在创建对象时如果用不到这些数据也必须提供

            <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" >
                <constructor-arg name="name" value="test"></constructor-arg>
                <constructor-arg name="age" value="18"></constructor-arg>
                <constructor-arg name="birthday" ref="now"></constructor-arg>
            </bean>
        <!--    配置一个日期对象-->
            <bean id="now" class="java.util.Date"></bean>
        
    2. 使用set方法提供(更常用)

      • 使用标签:property 出现位置:bean标签的内部

      • 标签中的属性:

        name:用于调用指定的set函数(常用)

        value:用于提供基本类型和String类型的数据

        ref:用于指定其他的bean类型的数据,它指的就是在spring的IoC核心容器中出现过的bean对象

      • 优势:创建对象时没有明确的限制,可以直接使用默认构造函数

      • 弊端:如果某个成员必须有值,则获取对象时有可能set方法没有执行

            <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2" >
                <property name="name" value="TEST"></property>
                <property name="age" value="21"></property>
                <property name="birthday" ref="now"></property>
            </bean>
        
    3. 使用注解提供

    注入集合数据

    • 使用set方法

      <bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl3">
              <property name="myStrs">
                  <array>
                      <value>AAA</value>
                      <value>BBB</value>
                      <value>CCC</value>
                  </array>
              </property>
      
              <property name="myList">
                  <list>
                      <value>AAA</value>
                      <value>BBB</value>
                      <value>CCC</value>
                  </list>
              </property>
      
              <property name="mySet">
                  <set>
                      <value>AAA</value>
                      <value>BBB</value>
                      <value>CCC</value>
                  </set>
              </property>
      
              <property name="myMap">
                  <map>
                      <entry key="testA" value="AAA"></entry>
                      <entry key="testB">
                          <value>BBB</value>
                      </entry>
                  </map>
              </property>
      
              <property name="myProps">
                  <props>
                      <prop key="testC">CCC</prop>
                      <prop key="testD">DDD</prop>
                  </props>
              </property>
          </bean>
      
    • 用于给List结构集合注入的标签:List array set

    • 用于给map结构集合注入的标签:map props

02 spring基于注解的IoC

基于注解的IoC配置

步骤
  1. 在xml文件中,告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
        
        <!--告知spring在创建容器时要扫描的包-->
        <context:component-scan base-package="com.itheima"></context:component-scan>
    
    </beans>
    
  2. 在想要创建bean对象的类前加上对应注解,如:

    /**
     * 账户的业务层实现类
     */
    @Component(value = "accountService")
    public class AccountServiceImpl implements IAccountService {
         
        private IAccountDao accountDao = new AccountDaoImpl();
    
        public void saveAccount(){
         
            accountDao.saveAccount();
        }
    }
    
常用IoC注解按照作用分类
  1. 用于创建对象的:作用和xml中编写一个标签实现的功能一样

    • @Component:

      作用:用于把当前类对象存入spring容器中

      属性:

      • value:用于指定bean的id,当我们不写时,它的默认值是当前类名且首字母改为小写
    • @Controller:一般用在表现层

    • @Service:一般用在业务层

    • **@Repository:**一般用在持久层

      以上三个注解的作用和属性与Component一模一样,它们三个是spring框架为我们提供明确的三层使用的注释,使我们的三层对象更加清晰

  2. 用于注入数据的:和xml中编写标签的作用一样

    • @Autowired:

      ​ 作用:自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功,如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错。如果ioc容器中有多个匹配时,默认报错:

      ​ 当有只有一个匹配时,自动按照类型注入。

      ​ 有多个匹配时,先按类型查找,再按变量名匹配。

      ​ 出现位置:可以是变量上,也可以是方法上。

      ​ 细节:在使用注解注入时,set方法就不是必须的了

    • @qualifier

      作用:在按照类中注入的基础上再按照名称注入,它在给类成员注入时不能单独使用,但是在给方法参数注入时可以。

      属性:value:指定注入bean的id。

    • @Resource

      作用:直接按照bean的id注入,它可以独立使用

      属性:name:用于指定bean的id

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值