初学者都看得懂的spring的相关知识(一)

spring的主要内容

在这里插入图片描述

背景

在这里插入图片描述

  • EJB的缺点
    在这里插入图片描述
  • spring的知识

是一个轻量级的Java EE解决方案,整合了众多的设计模式

  1. 轻量级

对运行的环境没有额外的要求,只需要有servlet的引擎即可以使用,可以选择开源的服务器,如tomcat。也可以选择收费的。代码的可移植性高,不需要实现额外的接口。

  1. Java EE解决方案
    在这里插入图片描述

之前学过的structs2和mybatis只是解决分层开发中某一层的问题,spring可以解决分层开发中各个层次的问题。是一个总体的解决方案。在着其中整合了各种的设计模式,正式由于这些设计模式,如工厂模式模板观察者模式代理模式才可以对分层开发中的各个层次进行整合和解决。

设计模式

  1. 广义:在面向对象的的过程中,解决某中问题的特定代码
  2. 狭义:GOF4提出的经典23中设计的模式,如工厂,适配器,代理…
工厂设计模式

概念:通过工厂类的方式来创建对象。
优点:可以降低耦合,接口的实现类由工厂进行创建,在分层中,当接口的实现类进行改变的时候,不需要更改另一层。在controller中通过new serviceimpl的方式,当接口的实现类构造方法进行改变的时候,耦合不利于代码的维护,controller也需要进行改变,通过工厂的方式不需要改变controller,只需要改变工厂即可。

  • 没用工厂模式的代码
public interface UserDao {
    String login(String username);
}
public class UserDaoImpl implements UserDao {
    public String login(String username) {
        return String.format("用户名为%s的用户登录成功",username);
    }
}
public interface UserService {
    //模拟用户登录
    String login(String username);
}

public class UserServiceImpl implements UserService {
	//在这里使用了new,增加了耦合,当需要更改实现类的时候还需要更改这个操作
    private UserDao userDao = new UserDaoImpl();
    public String login(String username) {
        return userDao.login(username);
    }
}

结果测试

 @Test
    public void testDemo(){
        UserService userService = new UserServiceImpl();
        System.out.println(userService.login("admin"));
    }
  • 使用了工厂模式
public class MyBeanFactory {

    public static UserService getUserService(){
        return new UserServiceImpl();
    }
}
 UserService userService = MyBeanFactory.getUserService();
        System.out.println(userService.login("admin"));

这种情况下还是耦合,只是将耦合转移到了简单工厂里面

  • 继续改进,使用配置文件的方式进行,利用反射创建对象
userService = com.demo.service.impl.UserServiceImpl
 private static Properties properties = new Properties();
    //在加载类时读取配置文件
    static {
        InputStream inputStream = MyBeanFactory.class.getResourceAsStream("/bean.properties");
        try {
            properties.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static UserService getUserService(){
        String userService = (String) properties.get("userService");
        UserService service = null;
        try {
            service = (UserService) Class.forName(userService).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return service;
    }
  • 终极版改进,通用工厂类,需要更改实现只需要更改配置文件即可
    传入配置文件的key,然后根据key去查找要创建的类的值
 private static Properties properties = new Properties();
    //在加载类时读取配置文件
    static {
        InputStream inputStream = MyBeanFactory.class.getResourceAsStream("/bean.properties");
        try {
            properties.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String key){
        String value = (String) properties.get(key);
        Object result = null;
        try {
            result =  Class.forName(value).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return result;
    }
  • 通用工厂的使用方式
  1. 定义类型 (类)
  2. 通过配置文件的配置告知工厂(applicationContext.properties)
    key = value
  3. 通过工厂获得类的对象
    Object ret = BeanFactory.getBean(“key”)

spring的基础

  • 导入依赖包
#设置pom 依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.1.4.RELEASE</version>
</dependency>
  • 写配置文件
  • 进行相应的测试

每个框架中都有相应的核心类,如mybatis中核心类为sqlsessionfactory,在spring中核心类为application Context,该类是一个接口,主要的两个实现为classPathApplicationContextwebApplicationContext,后者需要又web容器的支持。
该核心类属于重量资源,在创建的时候会占用大量的内存,因此要保证单例和多线程情况下的安全

spring的快速开始(对比通用工厂类)
  1. 自定义需要的类
  2. 写配置文件
  3. 测试
    <bean id="userService" class="com.demo.service.impl.UserServiceImpl"></bean>
 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService.login("admin"));

在获取bea的时候可以根据id进行获取,也可以根据类型进行获取,也可以获取所有bean定义的名字
工厂的相关方法

//通过这种方式获得对象,就不需要强制类型转换
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);
        

//当前Spring的配置文件中 只能有一个<bean class是Person类型
Person person = ctx.getBean(Person.class);
System.out.println("person = " + person);
        

//获取的是 Spring工厂配置文件中所有bean标签的id值  person person1
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
  System.out.println("beanDefinitionName = " + beanDefinitionName);
}
        

//根据类型获得Spring配置文件中对应的id值
String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
for (String id : beanNamesForType) {
  System.out.println("id = " + id);
}
        

//用于判断是否存在指定id值得bean
if (ctx.containsBeanDefinition("a")) {
  System.out.println("true = " + true);
}else{
  System.out.println("false = " + false);
}
      

//用于判断是否存在指定id值得bean
if (ctx.containsBean("person")) {
  System.out.println("true = " + true);
}else{
  System.out.println("false = " + false);
}

配置文件的细节

1. 只配置class属性
<bean  class="com.baizhiedu.basic.Person"/>
a) 上述这种配置 有没有id值 com.baizhiedu.basic.Person#0
b) 应用场景: **如果这个bean只需要使用一次,那么就可以省略id值**
            如果这个bean会使用多次,或者被其他bean引用则需要设置id值


2. name属性
作用:用于在Spring的配置文件中,为bean对象定义别名(小名)
相同:
   1. ctx.getBean("id|name")-->object
   2. <bean id="" class=""
      等效
      <bean name="" class=""
区别:
   1. **别名可以定义多个,但是id属性只能有一个值**
   2. XML的id属性的值,命名要求:必须以字母开头,字母 数字 下划线 连字符 不能以特殊字符开头 /person
         name属性的值,命名没有要求 /person
      name属性会应用在特殊命名的场景下:/person (spring+struts1)
      
      XML发展到了今天:ID属性的限制,不存在 /person
   3. 代码
         //用于判断是否存在指定id值得bean,不能判断name值
        if (ctx.containsBeanDefinition("person")) {
            System.out.println("true = " + true);
        }else{
            System.out.println("false = " + false);
        }


        //用于判断是否存在指定id值得bean,也可以判断name值
        if (ctx.containsBean("p")) {
            System.out.println("true = " + true);
        }else{
            System.out.println("false = " + false);
        }

配置文件中的一些注意点

a) 上述这种配置 有没有id值 com.baizhiedu.basic.Person#0 b) 应用场景: 如果这个bean只需要使用一次,那么就可以省略id值 如果这个bean会使用多次,或者被其他bean引用则需要设置id值,类似于匿名对象

name与id的一些区别
用于在Spring的配置文件中,为bean对象定义别名(小名),name可以有多个,id必须保证唯一。

spring工厂的底层的实现
在这里插入图片描述
主要是通过反射,也可以调用私有的构造方法
实体类通常不交给spring进行管理,主要通过DAO进行创建

注入的相关知识

注入的概念

通过spring或者配置文件为对象的属性复制的操作成为注入
优点:通过编码的方式为对象赋值会有耦合,注入可以解耦合,不需要更改代码,更改属性的值的时候不需要更改代码。

注入的实现方式

  1. set方法
 <bean id="person" class="com.baizhiedu.basic.Person">
   <property name="id">
     <value>10</value>
   </property>
   <property name="name">
     <value>xiaojr</value>
   </property>
</bean>

set注入的详解
在这里插入图片描述
基本类型

<property name="age">
            <value>12</value>
        </property>
        <property name="name">
            <value>张三</value>
        </property>
        <property name="tel">
            <list>
                <value>123456</value>
                <value>12345</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="a" value="1"></entry>
                <entry key="b" value="2"></entry>
            </map>
        </property>
        <property name="strings">
            <array>
                <value>aaa</value>
                <value>bbb</value>
            </array>
        </property>
        <property name="properties">
            <props>
                <prop key="a1">1</prop>
                <prop key="a2">2</prop>
            </props>
        </property>

自定义类型

  1. 使用内部bean
 <property name="userDAO">
       <bean class="xxx.UserDAOImpl"/>
  </property>
  1. 使用ref
<bean id="userService" class="xxx.UserServiceImpl">
   <property name="userDAO">
        <ref bean="userDAO"/>
  </property>
</bean>

基于p命名空间的简化
导入p命名空间,然后进行设置相应的值。

<bean id="userService" class="xxx.UserServiceImpl" p:userDAO-ref="userDAO" p:name="张三"/>
  1. 构造注入(不常用)
    主要在框架中中使用。
<bean id="customer" class="com.baizhiedu.basic.constructer.Customer">
  <constructor-arg> 一个该标签代表构造方法的一个参数
    <value>suns</value>
  </constructor-arg>
  <constructor-arg>
    <value>102</value>
  </constructor-arg>
</bean>

在这里插入图片描述

反转控制和依赖注入
  1. 反转控制(ioc)
    所谓的控制就是对成员变量的而控制权,之前对成员变量的控制权在我们手上,直接在代码中进行属性的赋值。现在转移到spring框架上。底层实现是工厂设计模式,可以解耦合
    在这里插入图片描述
  2. 依赖注入
    通过spring+配置文件的方式为属性进行赋值。

spring创建复杂的对象

  1. 何为复杂的对象?
    不能直接通过new的方式得到的对象成为复杂的对象。
  2. 创建的方式?
    使用继承factoryBean接口;
public class TestFactoryBean implements FactoryBean<User> {
    public User getObject() throws Exception {
        User user = new User();
        user.setAge(12);
        user.setName("这是测试");
        return user;
    }

    public Class<?> getObjectType() {
        return User.class;
    }

    public boolean isSingleton() {
        return true;
    }
}

相应的配置

 <bean id="myBeanFactory" class="com.demo.po.TestFactoryBean"></bean>

如果不想与spring进行耦合,也可以使用静态的方法。

在这里插入图片描述
在这里插入图片描述
可以通过scope或者isSigton来控制是否单例,有些单例,有些事需要多例
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值