Spring的基础知识(IOC)

EJB

EGB运行环境苛刻,造价高昂,代码扩展性差,移植性差,被视为重量级框架。

weblogic和websphere作为收费且不开源的应用服务器,许多中小型企业无法使

用,且无法进行定制和修改。

Spring?

spring是一个轻量级的javaee解决方案,整合众多优秀的设计模式

1.轻量级

1.对于运行环境没有要求

tomcat resion jetty 开源

weblogic websphere 收费

2.代码移植性高

不需要额外接口

2.javaee解决方案

3.整合设计模式

工厂 代理 模板 策略

设计模式

1.广义概念

面向对象设计中,解决特定问题的经典代码

2,狭义概念

gof4人帮定义的23种设计模式:工厂 式:工厂,适配器,装饰器,门面,代理,模板。

工厂设计模式

1.通过工厂类进行创建对象

传统方式创建对象

User user = new User();

UserDao userDao = new UserDaoImpl

2.好处:解耦合

耦合:指定的是代码间的强关联关系,一方的改变会影响到另一方.

问题:不利于代码的维护

简单:接口的实现类硬编码在程序中

简单的工厂设计模式

会存在大量代码冗余

通用的工厂设计模式

可以创建一切想要创建的对象

通用的工厂的使用方式

1.定义类型 (类)

2.通过配置文件的配置来告诉工厂(applicationContext.properties)

key=value

3.通过工厂获得类的对象 Object ret = BeanFactory.getBean(key);

总结:

spring本质:工厂 ApplicationContext.xml

spring环境搭建

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.12.RELEASE</version>
</dependency>
1.配置文件的放置位置:任意位置 没有硬性要求
2.配置文件的命名:没有硬性要求 建议使用 applicationContext.xml

spring的核心API

ApplicationContext

1.作用 spring提供的ApplicationContext这个工厂,用于对象的创建

2.好处:解耦合

ApplicationContext接口类型

1.接口:屏蔽实现的差异

2.非web环境: ClasspathXmlApplicationContext (main junit)

3.web环境: XmlApplicaitonContext

重量级资源

1.ApplicationContext工厂的对象占用了大量的内存资源。因此不能够频繁的创建对象,一个应用程序只会创建一个内存对象

2.ApplicaitonContext工厂:一定是线程安全的。

程序开发

1.创建对象

2.配置文件的配置 applicationContext.xml

id 唯一 class 全限定名称

3.通过工厂类,获得对象

ApplicationContext

ClasssPathXmlApplicationContext

ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
// 当前spring配置文件中只能有一个Person类型 否则会抛出异常
Person person = ctx.getBean("person", Person.class);
System.out.println("person = " + person);

细节分析

spring工厂创建的对象叫做bean或者组件component

@Test
    public void test02() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
        // 获得spring配置文件中所有的id值
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
        //根据类型获取spring配置文件中所有对应的id值
        String[] beanNamesForType = ctx.getBeanNamesForType(Person.class);
        for (String beanName : beanNamesForType) {
            System.out.println(beanName);
        }
        //判断是否存在id为person的bean
        boolean person1 = ctx.containsBean("person");
        //判断是否存在id或者name为person的bean
        boolean person11 = ctx.containsBeanDefinition("person1");
        Person person = ctx.getBean("person", Person.class);
        System.out.println("person = " + person);
    }

配置文件需要注意的细节

  1. 只配置class属性

上述这种配置 有没有id值 默认:beanDefinitionName = com.baizhi.basic.Person#0

应用场景: 如果这个bean只需要使用一次的话,那么就可以省略id值

如果这个bean回事哟个多次,或者被其他的bean引用 则需要设置id值
  1. name属性

作用:用于在spring配置文件中,为bean对象定义别名(小名)

相同:1.Person p = ctx.getBean(“p”, Person.class);

2.

区别:别名可以定义多个 ,但是id只能有一个

xml id属性值,命名要求:必须以字母开头,字母 数字 下划线 连字符,但是发展到今天,没有了限制

name属性值之没有任何要求的 应用在特殊的场景下

3.代码

//判断是否存在id为person的bean
boolean person1 = ctx.containsBean("person");
//判断是否存在id或者name为person的bean
boolean person11 = ctx.containsBeanDefinition("person1");

spring工厂底层实现原理简易版

未来在开发的过程中,是不是所有的对象都可以交给spring工厂进行创建的?

理论上:是的 但是有特例:实体对象(entity)对应着数据库中的数据,由持久层框架进行创建。

spring与日志框架整合

spring与日志框架进行整合可以在控制台中输出spring框架运行过程中的一些重要的信息

好处:可以了解spring框架的运行过程,利于程序的调试

整合log4j:

1.引入jar

<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>

2.引入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-dd
HH:mm:ss} %-5p %c{1}:%L - %m%n

注入

1.什么是注入?

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

2.为什么需要注入

通过编码的方式为对象进行赋值,会造成耦合。

开发步骤

1.为类对象提供set get方法

2.配置spring的配置文件

<bean id="person" name="p,p1,p2" class="com.baizhi.basic.Person">
  <property name="id" value="1"></property>
  <property name="name" value="yangShen"></property>
</bean>

3.注入的好处:解耦合

spring注入原理分析的简易版

Spring通过底层调用对象属性对应的set方法,完成成员变量的赋值,这种方式我们称之为set注入。

set注入

JDK内置

1.String+八种基本数据类型

2.数组

<list>
    <value>1020917713@qq.com</value>
    <value>1020912313@qq.com</value>
    <value>1043912313@qq.com</value>
 </list>

3.set集合

<set>
    <value>123</value>
    <value>1234</value>
    <value>12345</value>
 </set>

 <set>
   <ref bean=>
 </set>

4.list集合

<list>
    <value>1020917713@qq.com</value>
    <value>1020912313@qq.com</value>
    <value>1043912313@qq.com</value>
    <ref bean= ></ref>
 </list>

5.map集合

map — entry – key由特定的标签

值根据特定的类型选择对用类型的标签

<entry>
   <key><value>yangShen</value></key>
   <value>1020917713</value>
</entry>
<entry>
   <key><value>yangAo</value></key>
   <value>2390596320</value>
   <ref bean=>
</entry>

6.Properties

特殊的map key value 都是String 类型

<property name="properties">
   <props>
      <prop key="key1">yangshen</prop>
      <prop key="key2">yangao</prop>
   </props>
</property>
用户自定义类型

1.第一种方式

<bean id="userService" class="xxx.UserServiceImpl">
  <property name="userDao">
      <bean class="xxx.UserDaoImpl"></bean>
  </property>
</bean>

存在的问题:1.配置文件的冗余 2.被注入的对象多次创建,浪费jvm资源。

2.第二种方式

<bean id="userDao" class="xxx.UserDaoImpl"></bean>
<bean id="userSerice" class="xxx.UserviceImpl">
  <property name="userDao">
    <ref bean="userDao"></ref>
  </property>
</bean>

spring4.x 废除了 <ref local=""/> 基本等效 <ref bean=""></ref>
set注入简化写法

1.重要

<property name="name" value=""></property>
<property name="name" ref=""></property>

2.基于p命名空间简化 了解即可

<bean id="person" class="com.baizhi.basic.Person" p:name="yangShen"></bean>

构造注入

开发步骤:

1.提供有参构造方法

public class Customer implements Serializable {
    private String name;
    private int age;

    public Customer() {}

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.spring的配置文件

<bean id="customer" class="com.baizhi.basic.constructor.Customer">
    <constructor-arg>
       <value>yangShen</value>
    </constructor-arg>
    <constructor-arg>
       <value>12</value>
    </constructor-arg>
 </bean>

构造方法的重载,如何进行注入?

<constructor-arg type="java.lang.String"></constructor-arg>

反转控制(IOC)

控制:对于成员变量赋值的控制权

反转控制:把成员变量赋值的控制权,从代码转移到spring的工厂和配置文件中。底层原理:工厂设计模式

依赖注入

当一个类需要另一个类的时,就意味着依赖,一旦出现依赖,就可以把另外一个类作为本类的成员变量,最终通过spring工厂和配置文件进行注入(赋值)

什么是复杂对象?

spring工厂创建复杂对象的三种方式

1.FactoryBean接口

开发步骤:

1.实现FactoryBean接口

public class ConnectionFactoryBean implements FactoryBean<Connection> {

    @Override
    public Connection getObject() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        return DriverManager.getConnection("jdbc:mysql:///db", "root", "1234");
    }

    @Override
    public Class<?> getObjectType() {
        return Connection.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

2.Spring配置文件的配置

# 如果Class中指定的类型是FactoryBean接口的实现类,那么通过id值获得的是这个类所创建的复杂对象
<bean id="conn" class="com.baizhi.basic.factorybean.ConnectionFactoryBean"></bean>

细节:

1.如果就像获得FactoryBean对象的话,写ctx.getBean(“&conn”);

2.isSingleton 返回true的时候 创建一个复杂对象 反之 则会创建多个对象

3.mysql高版本连接的时候,需要指定SSL证书,解决的方式为:

url="jdbc:mysql://localhost:3306/db?useSSL=false"

2.实例工厂

1.避免spring框架的侵入 防止过度依赖

2.整合遗留系统

public class ConnectionFactory {

    public Connection getConnection() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///db", "root", "1234");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
}
<bean id="connFactory" class="com.baizhi.basic.factorybean.ConnectionFactory"></bean>

 <bean id="conn" factory-bean="connFactory" factory-method="getConnection"/>

3.静态工厂

public class ConnectionStaticFactory {

    public static Connection getConnection() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql:///db", "root", "1234");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
}
<bean id="conn" class="com.baizhi.basic.factorybean.ConnectionStaticFactory" factory-method="getConnection"></bean>

总结:

Singleton

对象只会创建一次

Prototype

每一次创建新的对象

对象的生命周期

一个对象创建 存活 消亡的整个过程

生命周期的三个阶段:

1.创建阶段

Spring工厂何时创建对象?

scope=“singleton”

工厂创建的时候同时创建对象,

如果不想要工厂创建的同时实例化对象,只需要加:

lazy-init="true"

scope=“prototype”

只有当获取ctx.getBean()的时候才能创建对象

2.初始化阶段

spring工厂在创建完对象的时候,调用对象的初始化方法,完成初始化的操作

初始化操作是对资源的初始化 例如 数据库 io 网络

1.初始化方法是由程序员根据需求来提供的

2.初始化方法是由spring工厂来进行调用的

实现方法

第一种方式:实现InitializingBean接口

第二种方法:提供一个普通的方法,只需要在配置文件中进行配置就可以了 因为要告诉spring

init-method="afterPropertiesSet"

细节分析:

如果一个对象既实现了InitializingBean接口,由提供了普通的初始化方法,顺序为:执行接口中的方法在去执行普通方法

创建对象 属性注入 初始化 使用 销毁

3.销毁阶段(只适用在singleton中)

spring销毁对象前 会调用对象的销毁方法 完成销毁操作(资源的释放) 工厂关闭前进行销毁操作

第一种方式:实现DisposableBean接口

@Override
public void destroy() throws Exception {

}

第二种方法:提供一个普通的方法,只需要在配置文件中进行配置就可以了 因为要告诉spring

destroy-method=""
  1. 细节分析:

如果一个对象既实现了DisposableBean接口,由提供了普通的初始化方法,顺序为:执行接口中的方法再去执行普通方法

创建对象 属性注入 初始化 使用 销毁

配置文件参数化

把spring配置文件中需要经常修改的字符串转移到更小的配置文件当中

自定义类型转换器

spring通过类型转换器把配置文件中的字符串类型的数据,转换成对象中成员变量对应类型的数据,进而完成了注入。

为什么需要类型转换器?

当spring内部没有提供特定类型的转换器时,而程序员在应用过程中还需要使用,那么就需要程序员自己定义类型转换器。

1.自己编写一个类实现Converter接口

public class MyConverter implements Converter<String, Date> {

    /**
     *
     * @param source 代表配置文件中的字符串 也就是你需要转换的东西
     * @return spring自动会把转换完成的东西赋值
     */
    @Override
    public Date convert(String source) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = simpleDateFormat.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

2.告诉spring

<!--   创建converter类型转换器-->
   <bean id="myConverter" class="com.baizhi.basic.convert.MyConverter"></bean>

<!--   注册类型转换器 conversionService必须叫这个 大小写也必须是这样-->
   <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
      <property name="converters">
         <set>
            <ref bean="conversionService"></ref>
         </set>
      </property>
   </bean>

后置处理bean

BeanPostProcessor:对spring工厂所创建的对象,进行再加工

程序员实现接口中的方法即可,spring会自动调用该方法

实战当中很少使用,仅仅了解就ok了

细节:BeanPostProcessor会对spring工厂中所有创建的对象进行加工。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_yangshen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值