Spring1

    xiaoxiao2022-07-08  195

    Spring 学习(1)

    分层架构 web 层 ---- Spring MVC | strutsservice 层 ---- Springdao 层 ---- Mybatis | JDBCTemplate | hibernate —> Spring-date

    Spring 核心

    Spring 核心是控制反转(Ioc) 和面向切片(Aop) IocAop

    Spring 优点

    方便解耦,简化开发(高内聚、低耦合)

    Spring 就是大工厂(容器),用于生成Bean

    Aop 编程的支持

    声明式事务的支持

    方便程序的测试

    方便集成各种优秀的框架

    降低JavaEE Api 的使用难度

    Spring 体系结构

    核心容器: beans、core、context、expression

    Spring开发:

    入门案例:Ioc(控制反转)

    导入jar 包和依赖
    jar 包 spring-expression-4.3.18.RELEASE.jar spring-context-4.3.18.RELEASE.jar spring-beans-4.3.18.RELEASE.jar spring-core-4.3.18.RELEASE.jar
    依赖 commons-logging-1.2.jar

    目标类

    提供UserService 接口和实现类获取UserService 实现类的实例使用Spring 创建实例对象(Ioc 控制反转)
    UserService 接口 package com.spring1_Ioc; /** * @InterfaceName Userservice * @Author 秃头的JJ * Date 2019/5/21 0021 20:20 */ public interface Userservice { void springTest(); }
    UserServiceImpl 实现类 package com.spring1_Ioc.impl; import com.spring1_Ioc.Userservice; /** * @ClassName UserServiceImpl * @Author 秃头的JJ * Date 2019/5/21 0021 20:21 * Version 1.0 */ public class UserServiceImpl implements Userservice { @Override public void springTest() { System.out.println("Spring Hello"); } }

    配置文件

    配置文件位置任意,在开发中一般在classPath(src)下配置文件名称任意,开发中常用applicationContext.xml内容:添加schema 约束
    applicationContext.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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 配置bean bean:是需要创建的对象 id:实例的id class:实例的位置 --> <bean id="userServiceId" class="com.spring1_Ioc.impl.UserServiceImpl" > </bean> </beans>

    测试方法

    @Test public void springTest(){ /* 从Spring 容器获取 */ // 加载容器 String xmlPath = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath); // 从Spring 容器内获取实例 Userservice us = (Userservice) ac.getBean("userServiceId"); us.springTest(); }

    入门案例:DI(依赖注入) — 使用 子标签

    is a:是一个 — 继承has a:有一个 — 成员变量(依赖) 依赖:一个对象需要使用另一个对象注入:提供setter 方法进行另一个对象实例的设置

    目标类

    创建两个接口和实现类配置到xml 文件内
    Dao 接口 package com.spring2_DI; /** * @InterfaceName Dao * @Author 秃头的JJ * Date 2019/5/21 0021 21:39 */ public interface Dao { void daoTest(); }
    Dao 实现类 package com.spring2_DI.impl; import com.spring2_DI.Dao; /** * @ClassName DaoImpl * @Author 秃头的JJ * Date 2019/5/21 0021 21:39 * Version 1.0 */ public class DaoImpl implements Dao { public DaoImpl() { System.out.println("Dao Test DaoImpl"); } @Override public void daoTest() { System.out.println("Dao Test"); } }
    UserService_DI 接口 package com.spring2_DI; /** * @InterfaceName UserService_DI * @Author 秃头的JJ * Date 2019/5/21 0021 21:37 */ public interface UserService_DI { void DiTest(); }
    UserService_DI 实现类 package com.spring2_DI.impl; import com.spring2_DI.Dao; import com.spring2_DI.UserService_DI; /** * @ClassName UserService_DIImpl * @Author 秃头的JJ * Date 2019/5/21 0021 21:38 * Version 1.0 */ public class UserService_DIImpl implements UserService_DI { private Dao dao; private String str; public void setDao(Dao dao) { this.dao = dao; } public void setStr(String str) { this.str = str; } @Override public void DiTest() { System.out.println(this.str); } }

    配置文件

    property: 依赖注入所使用的标签 name: 所要输入的属性名称 ===== 要与实例化的类内的属性名称保持一致 ref: 指代需要传入的实例化对象的bean 的id value: 注入到属性的具体值 --> <bean id="UserService_DIImpl" class="com.spring2_DI.impl.UserService_DIImpl"> <property name="dao" ref="daoID"/> <property name="str" value="HelloWorld This Is A String" /> </bean> <bean id="daoID" class="com.spring2_DI.impl.DaoImpl"></bean>

    测试方法

    package com.spring2_DI.test; import com.spring2_DI.impl.UserService_DIImpl; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @ClassName MainTest * @Author 秃头的JJ * Date 2019/5/21 0021 20:31 * Version 1.0 */ public class MainTest { private static ApplicationContext ac; @BeforeAll public static void init(){ // 加载容器 String xmlPath = "applicationContext.xml"; ac = new ClassPathXmlApplicationContext(xmlPath); } @Test public void springTest(){ /* 从Spring 容器获取 */ // 从Spring 容器内获取实例 UserService_DIImpl us = (UserService_DIImpl) ac.getBean("UserService_DIImpl"); us.DiTest(); } }

    核心API

    BeanFactory

    用于生成任意Bean

    ApplicationContext采用延时加载,在第一次调用getBean() 时才会初始化Bean

    是BeanFactory 的子接口,功能更加强大(国际化处理、事件传递、Bean 自动装配、各种不同应用层的Context 实现)

    ClassPathXmlApplicationContext 用于记载classPath(src) 下的指定的XML 文件FileSystemXmlApplicationContext 用于记载指定盘符下的指定XML 文件

    基于XMl 的装配Bean

    Bean 的实例化方式

    三种Bean 的实例化方式:默认构造、静态工厂、实例工厂 默认构造 <bean id="" class=""> 必须提供默认构造 静态工厂 常用于Spring 整合其他框架(工具)用于生产实例,所有方法必须是static <bean id="" class="工厂的路径" factory-method="静态方法"> 实例代码
    applicationContext.xml <!-- 配置静态工厂 id: 静态工厂的id class:静态工厂的全路径类名 factory-method:静态工厂内的静态方法(创建类的方法) 由Spring 代理静态工厂,并调用创建类的方法,实现和FactoryName.FatoryMethodName() 一样的功能(输出被创建类的对象) --> <bean id="staticFactoryTest" class="com.spring3_static_factory.Factory" factory-method="createDao"></bean>
    自定义工厂类 package com.spring3_static_factory; /** * @ClassName User * @Author 秃头的JJ * Date 2019/5/22 0022 10:14 * Version 1.0 */ public class Factory { private static final Dao dao = new Dao(); public static Dao createDao(){ return dao; } }
    工厂实现类 package com.spring3_static_factory; /** * @ClassName Dao * @Author 秃头的JJ * Date 2019/5/22 0022 10:14 * Version 1.0 */ public class Dao { public void print(){ System.out.println("Hello Static Fatory"); } }
    测试方法 @Test public void staticFactoryTest(){ String xmlPath = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath); Dao dao = ac.getBean("staticFactoryTest", Dao.class); dao.print(); } 实例工厂 必须先有工厂实例对象,通过实例对象创建对象。提供的所有方法都是非静态的
    applicationContext.xml <!-- 实例工厂的使用:由Spring 创建工厂Bean 和待实现类的Bean factory-bean: 指代工厂类Bean 的id factory-method: 指代工厂类内创建实现类对象的方法 --> <!-- 创建实例工厂的Bean --> <bean id="factory" class="com.spring4_factory.Factory"></bean> <!-- 使用实例工厂的Bean 创建实现对象 --> <bean id="dao" factory-bean="factory" factory-method="createDao"></bean>
    Factory 工厂类 package com.spring4_factory; /** * @ClassName Factory * @Author 秃头的JJ * Date 2019/5/22 0022 10:55 * Version 1.0 */ public class Factory { private final Dao dao = new Dao(); public Dao createDao(){ return dao; } }
    待实现类 package com.spring4_factory; /** * @ClassName Dao * @Author 秃头的JJ * Date 2019/5/22 0022 10:55 * Version 1.0 */ public class Dao { public void print(){ System.out.println("Hello Factory"); } }
    测试方法 @Test public void factoryTest(){ String xmlPath = "applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath); Dao dao = ac.getBean("dao", Dao.class); dao.print(); }

    Bean 的种类

    普通Bean
    <bean id="" class=""> Spring 会直接创建class 对应类型的实例,并返回
    FactoryBean
    是特使的Bean ,具有工厂生产对象的能力,但是只能生产特点的对象. Bean 必须实现FactoryBean 接口, 该接口提供了getObject() 方法获取特点的Bean <bean id="" class="FactoryBean"> 先创建FactoryBean 实例,在调用getObject() 方法,并返回方法的返回值 类比于 FactoryBean fb = new FactoryBean(); return fb.getObject();
    注:
    BeanFactory 和FactoryBean 的区别 BeanFactory : 工厂,生产任意BeanFactoryBean : 是一个特殊Bean, 生产一个特定的Bean(过去代理对象的实例 AOP是使用)

    作用域

    作用域:用于确定Spring 所创建的Bean 的实例的个数 类别说明singleton*(单例,默认的)在Spring Ioc 容器内中仅存在一个Bean 实例,Bean 以单例方式存在,默认值prototype*(多例)每次从容器中调用Bean 时,都会返回一个新的实例request每次HTTP 请求都会创建一个新的Bean ,该作用域仅适用于WebApplicationContext 环境session同一个HTTP session 共享一个Bean, 不同Session 使用不同的Bean ,仅适用于WebApplicationContext 环境globalSession一般使用在Portlet 应用环境,仅适用于WebApplicationContext 环境 配置信息

    <bean id="" class="" scope="">


    applicationContext.xml <!-- 作用域:默认使用singleton (单例) singleton: 多例,每请求一次,创建一个新的实例 --> <bean id="scopTest" class="com.spring5_scope.ScopTest" scope="prototype" />
    ScopTest 测试类 package com.spring5_scope; /** * @ClassName ScopTest * @Author 秃头的JJ * Date 2019/5/22 0022 16:03 * Version 1.0 */ public class ScopTest { public void print(){ System.out.println(this.hashCode()); } }
    测试方法 @Test public void factoryTest(){ String xmlPath = "com/spring5_scope/applicationContext.xml"; ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath); ScopTest st = ac.getBean("scopTest", ScopTest.class); ScopTest st1 = ac.getBean("scopTest", ScopTest.class); System.out.println(st); System.out.println(st1); }

    生命周期

    Spring 生命周期(11个步骤)

    instantiate Bean 对象实例化populate properties 封装属性如果Bean 实现BeanNameAware 执行setBeanName如果Bean 实现BeanfactoryAware 或者 ApplicationContextAware 设置工厂setBeanFactory 或者上下文对象setApplicationContext如果存在类实现BeanPostProcessor(后处理Bean), 执行postProcessBeforeInitialization如果Bean 实现执行Initialization 执行afterPropertiesSet调用<bean init-method="初始化方法"> 指定初始化方法如果存在类实现BeanPostProcessor(处理Bean), 执行执行postProcessAfterInitialization执行业务处理如果Bean 实现DisposableBean 执行destory(销毁)调用<bean destory-method="“销毁方法"> 指定销毁的方法
    初始化和销毁
    在目标方法执行前和执行后,进行初始化和销毁

    <bean id="" class="" init-method="初始化方法" destory-method="销毁方法">

    销毁方法执行条件:1、必须调用Close 方法;2、必须时单例
    applicationContext.xml <!-- 定义初始化和销毁方法 init-method: 指定初始化方法(初始化方法可以为私有) destroy-method: 指定销毁方法(销毁方法可以为私有) 销毁方法执行条件:1、必须调用Close 方法;2、必须时单例 --> <bean id="lifecycle" class="com.spring6_lifecycle.LifeCycleBean" init-method="init" destroy-method="destory" />
    LifeCycleBean 测试Bean package com.spring6_lifecycle; /** * @ClassName LifeCycleBean * @Author 秃头的JJ * Date 2019/5/22 0022 16:45 * Version 1.0 */ public class LifeCycleBean { private void init(){ System.out.println("初始化方法"); } public void print(){ System.out.println("Hello Life Cycle Bean"); } private void destory(){ System.out.println("销毁"); } }
    测试方法 @Test public void lifeCycleTest() throws Exception { String xmlPath = "com/spring6_lifecycle/applicationContext.xml"; ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath); LifeCycleBean lcb = ac.getBean("lifecycle", LifeCycleBean.class); lcb.print(); /* 使用反射调用 close 方法 */ // ac.getClass().getMethod("close").invoke(ac); ac.close(); }
    BeanPostProcessor 后处理Bean
    Spring 提供的一种机制,需要实现此接口BeanPostProcessor,并将实现类提供给Spring 容器, Spring 容器自动执行,在初始化方法执行前执行befor(), 在初始化方法执行之后执行 after()Spring 提供工厂钩子,用于修改实例对象,可以生产代理对象,时AOP 的底层
    applicationContext.xml <!-- 配置测试Bean --> <bean id="testBean" class="com.spring7_BeanPostProcessor.pojo.TestBean" init-method="init" destroy-method="destory"></bean> <!-- 将BeanPostProcessor 实现类提供个Spring 进行管理 其逻辑类比于: A a = new A(); // 在这里调用BeanPostProcessor 实现类的before 方法 a = B.before(a); a.init(); // 在这里调用BeanPostProcessor 实现类的after 方法 a = B.after(a); // 调用a 的方法 a.print(); a.destory(); --> <bean class="com.spring7_BeanPostProcessor.pojo.BeanPostProcessorTest"></bean>
    BeanPostProcessor 实现类 package com.spring7_BeanPostProcessor.pojo; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** * @ClassName BeanPostPrecessorTest * @Author 秃头的JJ * Date 2019/5/22 0022 19:13 * Version 1.0 */ public class BeanPostProcessorTest implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization 执行了"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessAfterInitialization 执行了"); return bean; } }
    TestBean 测试类 package com.spring7_BeanPostProcessor.pojo; /** * @ClassName TestBean * @Author 秃头的JJ * Date 2019/5/22 0022 19:13 * Version 1.0 */ public class TestBean { private void init(){ System.out.println("初始化方法执行了"); } public void print(){ System.out.println("BeanPostPrecessorTest Say HelloWorld"); } private void destory(){ System.out.println("销毁方法执行了"); } }
    测试方法 private static ApplicationContext ac; @BeforeAll public static void init(){ String xmlPath = "com/spring7_BeanPostProcessor/applicationContext.xml"; ac = new ClassPathXmlApplicationContext(xmlPath); } @Test public void beanPostProcessorTest(){ TestBean tb = ac.getBean("testBean", TestBean.class); tb.print(); }

    属性的依赖注入

    属性依赖注入 — 构造方法(定义了有参构造器需要再定义无参构造器避免错误发生)
    applicationContext.xml 内Bean 方法配置 <!-- 使用构造器注入值:使用<constructor-arg> 标签 index: 指代有参构造器参数列表的第几位参数(从o 开始) value: 指代具体的参数值 ref: 传入另一个Bean name: 指代具体的参数名称 --> <bean id="user" class="com.spring9_DI_Contructor.pojo.User"> <constructor-arg name="password" value="12138"/> <constructor-arg name="username" value="12138"/> <constructor-arg name="userInfo" ref="info"/> </bean> <bean id="info" class="com.spring9_DI_Contructor.pojo.UserInfo"> <constructor-arg index="0" value="上官翠花"/> <constructor-arg index="1" value="女"/> <constructor-arg index="2" value="漕溪路"/> <constructor-arg index="3" value="1111级20班"/> </bean>
    属性依赖注入 — setter 方法(待实例化类内必须含有setter 方法)
    applicationContext.xml <!-- setter 方法实现参数注入:使用<property> 标签 name: 指代参数名称 value: 指代具体的要传入的值 <property name="" value="具体的值"> ==等价于==> <propery name=""> <value>具体的值</value> </property> ref: 指代需要传入的bean bean: 具体的bean 实例 --> <bean id="user" class="com.spring8_DI_setter.pojo.User"> <property name="username" value="12138"></property> <property name="password"> <value>12138</value> </property> <property name="userInfo" ref="info"></property> </bean> <bean id="info" class="com.spring8_DI_setter.pojo.UserInfo"> <property name="sex" value="男"></property> <property name="addr" value="春熙路"></property> <property name="class_" value="2222级05班"></property> <property name="name" value="欧阳铁柱"></property> </bean>
    属性依赖注入 — P命名空间
    对setter 方法注入进行简化,替换了 而是使用<bean p:属性名=“”"“普通值" p:属性名=”“引用值”>使用前提:需要添加命名空间在命名空间内加入:xmlns:p="http://www.springframework.org/schema/p"
    applicationContext.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- p:属性名=“"属性值" 作用与<property name="属性名" value="属性值"> 一样 但是在处理List 集合等数据不太友善 --> <bean id="user" class="com.spring10_DI_Pnamespace.pojo.User" p:username="12138" p:password="12138p" p:userInfo-ref="info"> <property name="strings"> <list> <value>HelloWorld1</value> <value>HelloWorld2</value> <value>HelloWorld3</value> <value>HelloWorld4</value> <value>HelloWorld5</value> <value>HelloWorld6</value> </list> </property> </bean> <bean id="info" class="com.spring10_DI_Pnamespace.pojo.UserInfo"> <constructor-arg index="0" value="上官翠花"/> <constructor-arg index="1" value="女"/> <constructor-arg index="2" value="漕溪路"/> <constructor-arg index="3" value="1111级20班"/> </bean>
    属性依赖注入 — SpEL
    对 进行同样编程,所有内容都使用value <property name="" value="#{表达式}">

    #{123}、#{‘String’} ----> 数字、字符串 #{beanID} ----> 引用另一个bean #{beanID.propName} ----> 操作属性 #{beanID.toString()} ----> 执行方法 #{T(静态类).字段或者方法} ----> 静态方法或字段的使用

    属性依赖注入 — 集合注入

    数组ListSetMap — 键值对 使用 子标签Properties (Props)

    集合的注入都是使用 的子标签


    applicationContext.xml <bean id="listTestId" class="com.spring12_DI_List.pojo.ListTest"> <property name="strs"> <!-- 注入数组值 --> <array> <value>欧阳铁柱</value> <value>上官翠花</value> <value>孙秃子</value> <value>李狗蛋</value> </array> </property> <property name="ints"> <array> <value>1</value> <value>2</value> <value>3</value> <value>4</value> </array> </property> <property name="stringList"> <!-- 注入List 集合值 --> <list> <value>欧阳铁柱</value> <value>上官翠花</value> <value>孙秃子</value> <value>李狗蛋</value> </list> </property> <property name="stringSet"> <!-- 注入Set 集合值 --> <set> <value>欧阳铁柱</value> <value>上官翠花</value> <value>孙秃子</value> <value>李狗蛋</value> </set> </property> <property name="map"> <!-- 注入Map 集合值 --> <map> <description>map Test</description> <!-- 使用entry 绑定键值对 --> <entry key="黄金缔造者" value="欧阳铁柱"></entry> <entry key="白银缔造者" value="上官翠花"></entry> <entry key="青铜缔造者" value="孙秃子"></entry> <entry key="黑铁缔造者" value="李狗蛋"></entry> </map> </property> <property name="props"> <!-- 注入Properties 值 --> <props> <prop key="黄金">欧阳铁柱</prop> <prop key="白银">欧阳铁柱</prop> <prop key="青铜">欧阳铁柱</prop> <prop key="黑铁">欧阳铁柱</prop> </props> </property> </bean>

    装配Bean 基于annotation (注解)

    注解: 实际上是一个Class ,使用 @注解名 来实现注解的作用就是简化开发,替代XML 配置文件使用注解的前提

    IOC 控制反转 ---- 创建Bean
    @Component(“id”) 取代 注解使用时,要添加命名空间,让Spring 扫描含有注解的Class 在web 开发中,提供了3个 @Component 衍生注解(功能是一样的) * @Repository --- Dao 层 * @Service --- service 层 * Controller --- 控制层(WEB 层)
    DI 依赖注入 ---- 对Bean 内参数进行赋值
    可以个私有字段设置值,也可以使用setter 方法进行设置 普通值: @Value(“值”)引用值: 使用类型注入 @Autowired 使用名称注入 (两种注入方式) @Autowired @Qualifier("名称") @Resource(name = “名称”)
    生命周期
    初始化:@PostConstruct销毁:@PreDestroy
    作用域
    @Socpe(“prototype”) ---- 多例

    XML 和注解配合使用

    一般是将所有Bean 配置在XML 内将所有依赖通过@Autowired 实现

    注: 1、默认情况这样配置无效,需要在xml 内配置<context:annotation-config> 2、<context:annotation-config>与 <context:component-scan> 不同时出现

    最新回复(0)