Spring初识

整合性框架,设计性框架

非侵入式:依赖注入是IOC的最经典表现

AOP:面向切面编程

OOP面向切面编程

Spring是一个容器因为它包含并管理应用对象的生命周期

springbeans包也就是Ioc实现的包

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd ">

    <!--
        <bean>:定义spring所管理的一个对象
        id:该对象的唯一标示,注意:不能重复,在通过类型获取bean的过程中可以不设置
        class:此对象所属类的全限定名
     -->
    <bean>


    </bean>

</beans>

 每一个bean相当于spring管理的一个对象

spring 配置支持单例

scope="singleton" 

IOC 和AOP

IOC

IOC 是什么?

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

 

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:

 

图2-1 传统应用程序示意图

当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图2-2所示:

 

图2-2有IoC/DI容器后程序结构示意图

IOC 能做什么?

IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

 

IOC 和DI:

 

DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

 

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

 

谁依赖于谁:当然是应用程序依赖于IoC容器;

为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;

谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;

 

●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

 

IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

如何获取spring beans 管理的bean 

//Person bean = (Person) applicationContext.getBean("person");
  //Person bean = (Person) applicationContext.getBean(Person.class);
  Person bean = applicationContext.getBean("person",Person.class);

IOC底层实质上就是一个对象工厂

1.IOC容器读取Bean实例以前,需要先将IOC容器本身实例化。

2.spring提供了IOC容器的两种实现方式,

2.1BeanFactoryIOC容器的基本试下是Spring内部的基础,是面向spring本身的

2.ApplicationContext BeanFactory的子接口,提供了高级的实现,几乎所有场合都何使用ApplicationContext而不是底层的BeanFactory

Application的基本实现类

 IOC把程序员的管理权反转给程序本身(反射)

DI 把具有依赖关系的属性进行赋值

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //相对路径,
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("");//绝对路径

xml的namespace作用:

作用就是规定我们只能在命名空间使用那些标签

p标签命名空间

 

<bean id ="student4" class="com.spring.demo.di.Student" p:age="11" p:name="liwenjie" p:sex="男" p:score="90">

value可以引用一些字面量数据没办法引用对象这个时候就需要ref 去当前容器管理下去找对于的id

ref 的两种实现方式

property

p:id命名-ref

<bean id ="student4" class="com.spring.demo.di.Student" p:age="11" p:name="liwen" p:sex="男" p:score="90" p:teacher-ref="teacter">
</bean>
<bean id="student" class="com.spring.demo.di.Student" >
    <property name="age" value="11"></property>
    <property name="name" value="frist"></property>
    <property name="sex" value="frist"></property>
    <property name="teacher" ref="teacter"></property>


</bean>

级联属性:

<bean id="student" class="com.spring.demo.di.Student" >
        <property name="age" value="11"></property>
        <property name="name" value="frist"></property>
        <property name="sex" value="frist"></property>
        <property name="teacher" ref="teacter"></property>

        <property name="teacher.tName" value="级联" ></property>
    </bean>

定义在内部的bean只能在定义bean的内部访问

<bean id="student6" class="com.spring.demo.di.Student" >
        <property name="age" value="11"></property>
        <property name="name" value="frist"></property>
        <property name="sex" value="frist"></property>
        <property name="teacher">
            <bean class="com.spring.demo.di.Teacher" id ="tt">
                <property name="tName" value="内部类"> </property>
                <property name="age" value="12"> </property>
            </bean>

        </property>
    </bean>

list map set 在xml中的表示

也可以使用util:list为其赋值

  <bean id="teacter2" class="com.spring.demo.di.Teacher">
        <property name="tName" value="集合"></property>
        <property name="age" value="12"></property>
        <property name="students">
            <list>
                <ref bean="student"/>
                <ref bean="student2"/>
                <bean name="stu" class="com.spring.demo.di.Student">
                    <property name="age" value="1"></property>
                </bean>
            </list>

        </property>
        <property name="map">
            <map>
                <entry>
                    <key>
                        <value>11</value>
                    </key>
                    <value>map测试</value>
                </entry>
            </map>
        </property>
        <property name="strings" ref="strings"></property>
        <property name="set" >
            <value>set测试</value>
        </property>
    </bean>
    <util:list id="strings">
        <value>util测试</value>
        <value>util测试2</value>
    </util:list>

工厂模式:就是隐藏对象的创建模式,我们获取类只需要通过工厂就可以,类创建的过程由工厂为我们实现。

spring分为两种bean 一种是不同bean 还有一种就是我们下面说到的FactoryBean

FactoryBean:

1.配置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"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:ref="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <bean id="myfatcory" class="com.spring.demo.FactoryBean.MyFactory"></bean>

</beans>

2.类

package com.spring.demo.FactoryBean;

/**
 * Created by lwj32 on 2020/6/4.
 */
public class Car {
    private String carName;
    private Double price;

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "carName='" + carName + '\'' +
                ", price=" + price +
                '}';
    }
}

3.工厂实现spring的FactoryBean

package com.spring.demo.FactoryBean;

import org.springframework.beans.factory.FactoryBean;

/**
 * Created by lwj32 on 2020/6/4.
 */
public class MyFactory implements FactoryBean<Car> {
    @Override
    public Car getObject() throws Exception {
        Car car =new Car();
        car.setCarName("宝马");
        car.setPrice(200000.0);
        return car;
    }

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

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

Spring中Bean的作用域scope

 

官网地址https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes-request

https://www.cnblogs.com/mfrank/p/10498056.html因为在最新版本(5.2.0.BUILD-SNAPSHOT)中request session早就被移除了

作用域设置为

prototype时两个的地址值时不相同的singleton是相同的

如果spring管理的容器有单例的话会在容器初始化的时候就创建对象,prototype因为每次使用就用到所以不一样

springbean生命周期:

1.调用构造方法创建对象

2.注入值

3.初始化

4.使用

5.销毁

bean的后置处理器(对所有bean进行操作)

package com.spring.demo.BeanLife;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Created by lwj32 on 2020/6/10.
 */
public class AfterHanlder implements BeanPostProcessor {
//初始化以前的操作
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        PeoPle peoPle = (PeoPle) bean;
        if(peoPle.getName().equals("zhangshan")){
            peoPle.setAge(1222);
        }else {
            return peoPle;
        }
        return peoPle;
    }
    //初始化以后的操作
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

引入静态文件:

通过springframework

<!--   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
           <property name="location" value="db.properties"></property>
       </bean>
    -->
    <context:property-placeholder file-encoding="utf-8" location="db.properties" ></context:property-placeholder>

自动装配

自动装配的属性给字面量的属性也就是ref 和嵌套bean

也可以通过

autowire="byName"

byName :通过spring管理的bean id 去匹配

 

byType 通过spring管理bean的类型去匹配

使用注解标识组件

@Component

@Repository

@Service

@Controller

添加注解的同时也要在xml中配置相关的扫描

<context:component-scan base-package="com.adguider">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

对设置注解的类进行进行扫描并创建bean,这些注释的类的bean的id是这些类的首字母小写作为id

组件扫描的包含和删除

这个时候我想过这么一个问题,为啥spring+springmvc中要 这样配置一个只扫描controller 一个不扫描controller这里面包含一个父子容器的关系

首先配置的是Spring容器的初始化加载的application文件,然后是SpringMVC的前端控制器(DispatchServlet),当配置完DispatchServlet后会在Spring容器中创建一个新的容器。其实这是两个容器,Spring作为父容器,SpringMVC作为子容器。

https://www.cnblogs.com/liu-eagles/p/7846944.html这个解释的非常明了。

//springmvc配置
<context:component-scan base-package="com.xxx" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>

    </context:component-scan>
//spring配置
   <context:component-scan base-package="com.xxx">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

大体理解就是

首先spring 和springmvc相当于两个容器而spring是父容器,springmvc为子容器,子容器可以访问夫容器中的bean,首先我我们在访问Controller时其中通过@Autowite可以访问父容器中的service其实这个道理和前面讲到的在bean标签中加入autowite是一个道理。

那么我们可以spring都去扫描吗回答是否定的,因为spring会加载controller 所以springmvc没有controller对象,无法提供服务

AOP解释

含义就是将我们要做的事情交给代理对象去做,最重要的是要保证最后结果一致。

代理模式实现

代理模式的三个对象:1.代理对象,2目标对象3.原始对象

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值