Spring笔记

文章目录

Spring

引言

  1. 软件的生命周期

开始: 开发完毕,初次使用。

结束: 软件升级和维护,代价非常大,大到不如重新开发。

  1. 现有代码的问题

获得对象: 在使用对象的位置,直接使用new的创建对象

缺点: 通过new的直接获得对象 ,存在耦合。

  1. 工厂设计模式

思想:

  1. 工厂对象 BeanFactory:获得对象,创建对象。
  2. 获得对象: 从工厂对象中,获得需要的对象。
  1. 总结工厂设计模式[重点]

核心思想

在这里插入图片描述

使用步骤:

  1. 将类信息注册在工厂的配置文件中。

  2. 编码:创建BeanFactory工厂。

  3. 编码:调用getBean方法,获得需要的对象。

    factory.getBean("要获得对象类名对应key")

Spring简介

简介: Spring是一个轻量级企业开发框架,核心: IOC编程,AOP编程。

IOC:[重要]

I(Inverse)  O(Of)   C(Controll)
控制反转
概念: 将对象创建的权利,转义到(Spring)工厂中。
目的: 将对象创建的耦合,解耦和。

Spring工厂

核心编程思想:
Spring工厂:
BeanFactory(接口):
    ApplicationContext(接口):
		//本地使用Spring工厂实现类:
	ClassPathXmlApplicationContext(实现类);----在本地环境下使用(主函数启动)
    XmlWebApplication(实现类); ---在web环境下使用。(从tomcat环境启动)

Spring配置文件:
	applicationContext.xml
	beans.xml

在这里插入图片描述

Spring环境搭建

  1. 导入需要的jar

    导入spring的jar

    导入spring依赖的commons-loggin的jar

  2. 导入配置文件。

    导入aopplicationContext.xml配置文件,src的任意目录下即可。

    导入log4j.properties配置文件,src的根目录下。

Spring工厂的使用步骤

核心思想

1544414447033.png

工厂步骤

1. 将类名信息注册在applicationContext.xml
   ① bean标签的class:类名信息
   ② bean标签的id:对应的名字   getBean(name)
   <bean class="全类名" id="获得该对象使用name">
2. 编码:创建spring工厂
   ApplicationContext factory = new ClassPathXmlApplicationContext(配置文件路径);
3. 编码:调用factory的getBean方法获得对象。
   factory.getBean("bean标签的id");
控制对象创建的次数
1. 默认spring工厂创建对象的次数  1个。(创建单个,单实例)
	应用: SqlSessionFactory  HttpServlet  DataSource(连接池)   XxxService
2. 创建多个
	bean scope="prototype"
	
	示例:
	<bean 
    	id="us" 
    	class="com.baizhi.demo1.UserServiceNewImpl" 
    	scope="prototype">
    </bean>
    应用: Action控制器(Controller)    SqlSession   Connection 

在这里插入图片描述

Spring工厂属性注入(属性赋值)

IOC DI思想

概念:

IOC Inverse Of Controll 反转控制(控制反转):

将对象创建的权利,从当前代码转移到spring工厂完成。

DI Dependency Injection 依赖注入

依赖: 对象的属性
依赖注入:给对象的属性赋值

总结[重点]

IOC/DI
反转控制 依赖注入
1. 将对象创建的权利转移到spring工厂中。
2. 将对象的属性赋值的权利,转移到了spring工厂中。

依赖注入的编码

  1. String+基本数据类+包装类型

    核心思路:

    1. 将对象交给spring工厂管理
    <bean id="" class=""></bean>
    2. 属性赋值--依赖注入
    	① 属性必须提供标准的get和set方法。
    	② 在配置文件完成。
    <bean id="" class="">
    	<property name="要赋值的属性名" value=""></property>
    </bean>
    
    补充:
    	String+基本数据类型包装类值表示
    	<property value="string或者int类型的值"></property>
    	<property>
    		<value>string或者int类型的值</value>
    	</property>
    

在这里插入图片描述
2. List和数组类型

<property name="list属性名">
	<!--list类型值-->
    <list>
    	<!--每个值: string 基本数据类型 包装类型-->
        <value>值1</value>
        <value>值2</value>
        <value>值3</value>
        <value>值4</value>
    </list>
</property>

在这里插入图片描述
3. Map

<property name="属性名">
	<!--map类型的值-->
    <map>
    	<!--map中每个元素包含key+value(entry)-->
        <entry key="key" value="value"></entry>
        <entry key="key1" value="value1"></entry>
        <entry key="key2" value="value2"></entry>
    </map>
</property>

1544429974105

  1. Properties

    1. Properties类型数据结构(key value)
    2. 使用spring工厂创建propertie啥类型的值,并给属性赋值
    <property name="属性名">
    	<props>
        	<prop key="k1">值value1</prop>
            <prop key="k2">值value2</prop>
        </props>
    </property>
    
    

    1544432765363

  2. 用户自定义类型

1544433542076

赋值原理
spring配置文件属性或者标签的底层原理
1. bean标签 class属性
	<bean id="user" class="com.baizhi.demo2.User">
	底层:
		String classstr = "com.baizhi.demo2.User";
		Class clazz = Class.forName(classstr);
		Object o = clazz.newInstance();
2. property标签  name属性   值
	作用: 给属性赋值。
	底层:
		调用的是property标签的name属性名对应的set方法【属性名首字母大写,前面添加set】
	总结:property标签的赋值原理是set方法。
使用有参构造方法给属性注入
1. 使用有参构造方法给属性赋值
<bean id="" class="">
    <!--使用有参构造方法给属性赋值
		index: 参数位置,序号
		value: 给的实际的参数。
	-->
	<constructor-arg index='参数序号,从0开始' value="101"></constructor-arg>
    <constructor-arg index='参数序号,从0开始' value="101"></constructor-arg>
</bean>

在这里插入图片描述

特殊对象的创建

比如:

Connection SqlSession DataSource SqlSessionFactory

//创建connection
1. 加载驱动
Class.forName("oracle.jdbc.OracleDriver");
2. 获得conn
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","hr","hr");
核心编码思路

思路:

  1. spring允许用户自己通过编写代码(实现FactoryBean接口),提供获得对象的方式。
  2. spring获得对象,可以借助于FactoryBean的getObjec方法获得对象。

在这里插入图片描述

编码步骤:
  1. 自定义类,告知spring如何获得对象。

    public class ConnectionFactory implements FactoryBean<Connection>{
        //spring获调用getObject方法,间接获得conn并管理在spring工厂中。
        public Object getObject(){
            //获得复杂对象的代码。
            
        }
        //该方法告知spring对象管理个数 。
        //return true;一个
        //return false;//多个。
        public boolean isSingleton(){
            return false;
        }
    }
    
  2. 将FactoryBean接口的实现类交给spring工厂管理.

    <bean id="connFactory" class="xxx.xxx.xxx.ConnectionFactory"></bean>
    补充:
    如果class对应的全类名实现FactoryBean接口
    ① bean标签作用就自动调用该类的getObject方法,获得对象,并将对象管理起来。
    ② 该被管理起来的对象的id "connFactory"
    
  3. 从spring工厂获得该connection对象

    factory.getBean("connFactory");
    作用: 获得 connFactory对应的bean标签的class对应的类的getObject方法的返回值。
    

总结

  1. SpringIOC /DI思想

    思想:反转控制,依赖注入,将对象创建的权利,从当前的代码中转移spring工厂中,对象属性赋值的权利转移到spring工厂中。

    编码:

    applicationContext.xml
    1. <bean></bean> 创建对象,并且将对象管理在spring工厂中.
    2. <property></property> 通过set方法给属性进行赋值。(依赖注入)
    3. <constructor-arg index="" value=""></constructor-arg> 通过有参构造方法给属性赋值。
    

    作用: 将代码的对象与对象之间的耦合,解耦和操作。

    应用:

    DAO  Service  Controller/Action   DataSource(连接池)  SqlSessionFactory(mybatis创建sqlsession)
    

    图:

在这里插入图片描述
2. IOC和DI的配置文件和编码

  1. 掌握特殊对象创建。

Spring AOP

引言

现有代码的问题:

  1. 事务代码耦合: 现有的事务控制的代码,耦合在了service方法中,一旦数据库访问技术发生变化,所有事务控制代码需要替换,导致service的代码被大量的修改!
  2. 事务控制的代码冗余: 大量相同的事务控制代码出现在了service方法中,出现冗余代码,不利于后期的升级和维护!

解决思路:

通过手动添加代理类,将事务控制代码放在代理类中。

在这里插入图片描述

代理类的核心规范 · 静态代理[重点]

  1. 先和目标类实现相同的接口
  2. 将额外功能(事务控制),放在代理类中。
  3. 调用目标对象的目标方法。

在这里插入图片描述

作用: 将事务代码和service的核心功能代码解耦和。

总结 代理类核心要素
  1. 和目标类相同的接口
  2. 额外功能
  3. 调用目标对象的方法。
  4. 代替目标对象接受调用.
静态代理的缺点

每个目标类都要书写一个代理类,存在代码冗余

Spring AOP·动态代理

动态代理: 使用技术动态为目标类生成代理类。

在这里插入图片描述

SpringAOP技术实现步骤

代理类核心
  1. 额外功能。
  2. 调用目标对象的方法
  3. 和目标类拥有相同的接口。
Springaop技术的核心思想
  1. 将额外功能的代码放在功能增强的对象中。
  2. springaop技术,将功能增强中的额外功能的代码,动态生成代理类,添加进去。
springaop的步骤
  1. 导入springaop依赖的jar。

asm cglib aspectj.awear

在这里插入图片描述

  1. 准备目标类,将目标类的对象交给spring管理。

  2. 书写额外功能所在的 功能增强类。

    public class 增强类 implements org.aopalliance.intercept.MethodInterceptor{
        /**
    	 * 额外功能:
    	 * 调用目标对象方法。
    	 */
    	@Override
    	public Object invoke(MethodInvocation mi) throws Throwable {
    		//1. 开启事务
    		System.out.println("开启事务");
    		
    		//2. 调用目标对象的功能。
    		Object o = mi.proceed();//调用真正的目标对象的方法。
    		
    		//3. 提交事务
    		System.out.println("提交事务");
    		return o;
    	}
    }
    
  3. 通过aop技术,动态生成代理类=额外功能+目标对象

    核心

    ① 额外功能加入的位置: 切入点

    告诉spring将额外功能代码放在哪个方法的内部[告诉spring将额外功能加入哪个类的哪个方法中。]

    ② 组装: 额外功能+类、方法(切入点)==代理类。
    在这里插入图片描述

SpringAOP编程思想

看起来

思想: AOP aspect orinted programing 面向切面编程。

在不修改目标的代码的情况下,动态的为目标类的方法添加额外的功能代码。

在这里插入图片描述

本质:

使用jdk技术,动态为目标类生成了代理类的,生成代理的对象,使用生成的代理对象替换了你的原始的目标对象。

民间解释: 偷梁换柱 偷天换日 李代桃僵 借尸还魂 狸猫换太子

在这里插入图片描述

MethodInterceptor详解
// 增强功能对象: 通知  建议。
public class XxxAdvice implements MethodInterceptor{
	/**
	 * 额外功能:
	 * 调用目标对象方法。
	 */
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		//mi: 代表目标对象的方法。
        Object o = mi.proceed();//调用目标对象的目标方法。
		return o;
	}
}
1. 获得目标对象的方法
	mi.getMethod();//Method 类型的目标方法。
2. 目标对象
	mi.getThis();//获得目标对象
3. 获得代理的目标方法的调用时,实际传入的参数
	mi.getArguments();//数组,实际传入的参数。
4. 调用目标对象的目标方法
	Object o = mi.proceed();//us.regist()     ps.add()
	//① 调用目标对象的方法
	//② 返回值代表实际被代理的方法的返回值。
	
切入点表达式详解

pointcut切入点: 告诉spring功能增强的目标类的目标方法

execution

语法: expression=“execution(切入点表达式)”

特点: 精确到方法声明的。

1. 精确点指定包指定类指定方法。
    execution(返回值 包名.子包.孙子包..方法名(参数1类型 参数2类型));

在这里插入图片描述

2. 精确到指定包下的指定类的执行方法,参数任意:
execution(返回值 包名.子包.孙子包..方法名(..));

3. 精确到指定包的指定类,方法名任意,参数类型任意
execution(返回值 包名.子包.孙子包..*(..));

4. 精确指定包下的任意类,任意方法,任意参数类型。
execution(返回值 包名.子包.孙子包.*.*(..));

5. 精确到指定包下的类,及其子包下的所有类的任意方法,任意参数
execution(* p1.p2.p3..*.*(..));
//将p1包下的p2包下的p3包下的所有类,及其子包下的所有类,任意方法,任意参数,任意返回值类型

within

语法: expression=“within(表达式语法)”

特点: 表达式的写法,只精确到类。

示例: within(包名.类名)

给指定包及其子包下的所有类。
within(p1.p2.p3..*);

@annotation

语法: expression="@annotation(注解全类名)"

特点: 凡是添加指定注解的方法,都会被功能增强。

使用步骤:

1. 定义注解。
public @interface HeheAdvice{}
//给定含义: 添加了HeheAdvice注解的方法,都会被功能增强。
2. 使用注解:
给需要功能增强的方法添加注解
public class AServiceImpl{
	@HeheAdvice
	//希望给a1方法做功能增强。
	public void a1(){}
}  
3. 通过切入点,指定:添加@HeheAdvice的方法,进行功能增强。

技术补充:

日志

记录代码运行中所有涉及到相关信息。

作用:

  1. 便于调错。
  2. 监控系统运行情况。

记录信息:

类 方法 参数 什么时间

如何使用日志:

1. 导入jar:commons-loggin.jar
2. 在需要使用日志位置:
	获得日志工具:
	Log log = LogFactory.getLog(所在的当前类的类对象);
	调用日志工具打印方法:
	log.info("日志信息");
重点:
  1. aop思想和本质

    思想(表面)

    在不修改目标类的代码情况下,动态为其添加额外功能代码,在目标方法之前运行一段代码,目标方法结束执行一段代码(位置: 目标方法一开始,目标方法最后)

    SpringAOP技术(本质):

    使用java技术,动态为目标类,生成代理类生成代理类的对象将代理对象替换原有的目标对象

    调用者在使用目标对象,被代理对象替换了【借尸还魂 李代桃僵】

    符合aop编程思想的技术:

    SpringAOP技术 过滤器 Struts2的拦截器

在这里插入图片描述
2. Springaop编码步骤(目标对象 曾强功能 切入点+组装)

1. 准备好目标类,且将目标对象交由spring管理: <bean>
2. 书写增强功能类,交给spring管理。[Advice 增强 切面 通知 建议]
3. 使用springaop技术[标签],组装生成代理类的对象,替换目标对象。
<aop:config>
	声明切入点: 
	<aop:pointcut id="pc" expression="execution(精确到方法)|within(精确类)|@annotation(指定添加的了注解全类名)">
	组装: 代理类=切入点+增强,   生成代理对象    将代理对象替换目标对象
	<aop:advisor pointcut-ref="pc" advice-ref="增强切面id"></aop:advisor>
</aop:config>
  1. 切入点表达式:execution和@annotation语法

    execution(返回值 包名.类名.方法名(参数类型1 参数类型2))

应用场景

核心思想:

抽取java代码中通用功能(冗余代码,重复代码),使用aop技术。

在这里插入图片描述>

应用场景:

  1. 事务控制。
  2. 日志打印。
  3. 性能监控。
  4. 权限(登录验证)–使用Filter 或者 拦截器

补充:功能增强的位置:

在这里插入图片描述


JdbcTemplate

Spring简化JDBC


谁: Spring提供的。(spring-jdbc.jar)

作用: 简化JDBC的代码。

常用API

  1. 如何获得JdbcTemplate

    1. 交给spring管理

    导入相关的jar:spring的jar 数据库驱动jar 阿里的连接池的jar

在这里插入图片描述

2. 如何从spring工厂获得JdbcTemplate

  1. 增删改方法
jdbcTemplate.update(sql,参数列表...)//执行增删改操作。

在这里插入图片描述

  1. 查询方法(查询单个)
T t = jdbcTemplate.queryForObject(sql,映射工具RowMapper接口,绑定参数);
//RowMapper:在这个对象中maprow方法,手动完成rs和实体映射关系。
//返回值:就是查询结果。

注意:查询没有结果,异常形式告知。

在这里插入图片描述

  1. 查询多条结果
List<T> list = jdbcTemplate.query(sql,RowMapper,绑定的参数);
//查询结果是多条数据。

Spring+JdbcTemplate开发应用

DAO层+Service层

编码步骤

  1. 实体

  2. 书写DAO

    实现类

  3. 开发Service

    实现类

Spring工厂的管理规范

  1. 需要spring管理的对象

    XxxxService
    XxxDAO
    JdbcTemplate
    dataSource连接池
    
  2. Spring容器内部对象管理
    在这里插入图片描述

    1. 补充:
    Spring管理对象:
    	功能性: JdbcTemplate  连接池  DAO  Service   Action
    不会使用spring管理:
    	数据型对象: 实体   XxxQuery对象
    

Spring声明式事务

思路:

  1. 将UserService作为目标类,管理在spring工厂。

  2. 配置管理spring提供,事务管理器。

封装了事务控制的方法。

  1. 使用spring工厂管理事务增强(spring内置事务增强)。

  2. 使用aop技术,为目标对象添加事务.

在这里插入图片描述
操作步骤:

  1. 管理service的目标类。
    在这里插入图片描述
  1. spring管理事务管理器。

  2. spring管理事务增强 tx:adivce 替代了 bean

在这里插入图片描述

  1. aop配置将增强加入service方法中

在这里插入图片描述

事务属性

事务属性配置标签和属性

<tx:attributes>
   <tx:method name="方法名1" read-only="只读" propagation="事务传播" rollback-for="回滚异常"></tx:method>
   <tx:method name="方法名2" ></tx:method>
   <tx:method name="方法名3" ></tx:method>
</tx:attributes>
  1. 事务回滚

    rollback-for: 指定service的方法,在什么异常情况下进行事务回滚操作。

    <tx:method name="regist" rollback-for="java.lang.RuntimeException"></tx:method>
    默认: rollback-for默认值 java.lang.RuntimeException
    
  2. 只读事务

    read-only: 只读。

    作用: 可以让serviec的查询方法在数据库的内存中,事务中,不分配回滚段。节省内存。

    应用: service方法只有读操作,建议设置为只读:read-only="true"

  3. 事务传播

    问题:service调用service

在这里插入图片描述

propagation=“SUPOORTS|REQUIRED”

SUPPORTS: 支持事务。

特点:

① 如果外部已经开始了事务,并融合到外部事务中。

② 如果外部没有开启事务,则不开启事务。

REQUIRED: 需要事务

特点:

必须要有一个事务。

① 如果外部已经开启事务,则融合外部事务中。

② 如果外部没有事务,则开启事务。

应用

1. 查询方法: 外部有事务,则融合,外部没有事务,没必要开启。 SUPPORTS
2. 添加,删除,修改业务方法: 外部已经开启事务,则融合。如果外部没有事务,则开启事务。REQUIRED

在这里插入图片描述

  1. 事务属性方法的简化

    <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
    含义: 只要service方法以get开头,都适用于,只读,支持事务这些设置。
    
    

Spring整合Struts2

问1: 将struts2的action交给spring管理。

核心思想:

ng)
在这里插入图片描述

问题2:spring工厂需要在Tomcat启动的时候就初始化完毕?

解决问题:

  1. ServletContextListener监听器的代码,可以在tomcat启动时执行的。
  2. 就spring工厂初始化的代码,放在ServletContextListener。

注: Spring内置ServletContextLisnter监听器,用来在tomcat启动的时候初始化spring工厂

org.springframework.web.context.ContextLoaderListener

开发步骤

环境搭建
  1. 导入相关的jar

    spring的相关jar
    struts2的相关的jar
    struts2-spring-plugins的jar
    commmons-logging日志jar
    
  2. 导入配置文件

    1. spring的配置文件【放在src下任意目录】
    	applicationContext.xml
    2. log4j日志文件【必须放在src根目录下】
    3. struts2的配置文件
    	struts.xml【必须放在src根目录下】
    4. web.xml配置文件。
    
  3. 初始化配置

    <!-- 1. struts2的核心控制器 -->
    	<filter>
    		<filter-name>struts2</filter-name>
    		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    	</filter>
    	<filter-mapping>
    		<filter-name>struts2</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    	<!--2. 初始化spring工厂的监听器  -->
    	<listener>
    		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    	<!--3. 手动指定配置文件路径  -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath:/applicationContext.xml</param-value>
    	</context-param>
    
开发Sturts2action
  1. action开发

  2. 交给spring管理 创建多个
    在这里插入图片描述

  3. 配置action的访问路径。

在这里插入图片描述

SSJ整合

Spring+Struts2+JdbcTemplate

搭建环境
1. 导入相关的资源(jar+配置文件)
    相关的jar
        spring相关
        struts2相关
        ojdbc5.jar
        druid连接池的jar
        struts整合spring的jar
        日志的jar
        aop依赖的jar
            asm-3.3.1.jar
            cglib-2.2.2.jar
            com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
   相关的配置文件
   		applicationContext.xml
   		struts.xml
   		log4j.properties
   		web.xml
 2. 初始化配置
 	环境搭建类型的初始化
 		struts核心控制器
 		spring工厂初始化监听器
 		指定spring配置文件路径。
 	编码相关的初始化
 		初始化spring配置文件中常用的内容
 		连接池
 		JdbcTemplate
 		txManager
 		tx:advice
 		aop:config

Spring工厂内部:

在这里插入图片描述

编写代码
注册功能:
1.2. 实体
3. DAO 和实现类  交给spring管asdf理。
4. Service和实现类,交给spring管理
5. Action,交给spring管理,scope="prototype"
   struts.xml注册action访问信息,跳转路径信息。
   <action name="" method="" class="action在spring工厂中的id">

Spring整合MyBatis

核心思想

在这里插入图片描述

环境搭建
  1. 导入jar

    1. spring jar
    2. mybatis jar
    3. aop 的jar
    4. ojdbc5.jar
    5. 连接池的jar
    6. 日志的jar
    7. mybatis-spring的jar。
       提供两个核心类:
       	SqlSessionFactoryBean  替代mybatis-config
       	MapperScannerConfigurer 代替mybatis生成dao对象的代码。
       		注意: 生成dao的id是对应接口的首字母小写。
    
  2. 导入配置文件

    1. applicationContext.xml
    2. log4.properties
    
  3. 初始化配置
    在这里插入图片描述

开发步骤

需求:书写DAO完成添加user的功能?

1.2. 实体
3. DAO接口
4. DAO接口对应的Mapper文件。
5. 获得dao,调用方法测试

SSM整合

搭建环境

1. 导入jar
	spring  mybatis struts2   mybatis整合spring  struts整合spring  aop  连接池 日志  ojdbc5.jar
2. 导入配置文件。
	struts.xml
	spring.xml
	log4j
	web.xml
3. 初始化配置
	web.xml配置
		① struts2核心控制器
		② spring工厂初始化的监听器
		③ spring配置文件路径
	
	applicationContext.xml
		① 连接池
		② 事务相关配置【txManager tx:advice aop】
		③ 初始化mybatis整合相关配置
			sqlSessionFactory
			生成dao对象

开发步骤

注册user功能

1.2. 实体
3. dao接口  
4. Mappe文件  spring自动管理dao对象。
5. Service接口
6. service实现类  Spring管理service对象
7. Action类
spring管理action 【创建多利】
映射action的访问路径和跳转路径  【class="action在spring工厂中的id"

Spring注解

开启spring注解:

applicationContext.xml
<context:component-scan base-package="com.baizhi"></context:component-scan>
作用:
Spring会扫描com.baizhi包下的类及其子包下的所有类,启动注解。

SpringIOC注解

有spring工厂创建对象,并管理对象

@Component
使用:在要交给spring工厂管理的类上。
语法:
@Component("对象在spring工厂中的id")
public class Xxxx{

}
作用:
1. 创建当前对象。
2. 交给spring工厂管理起来了。

在这里插入图片描述
2. 不指定对象的id

@Component
public class UserServiceImpl implements UserService{}
注意:当前对象在spring工厂中的id="userServiceImpl"
  1. spring管理多利对象

@Scope(“prototype”) 当前对象在spring工厂每次创建一个新的对象

@Component("userAction")
@Scope("prototype")
public class UserAction {
private UserService userService;
}
  1. 通常,只有程序员写的类,才能使用注解交给spring管理。

  2. 专门给三层结构类使用的**@Component**子注解

目的: 使用注解管理拥有分类语义。
特点: 和@Component功能和使用完全一致。
@Controller 控制器类
@Service    业务类
@Repository dao类使用

SpringDI注解

@Autowired

使用: 添加在属性上,需要通过spring工厂注入的属性。
作用: spring工厂会从工厂内,1. 查找符合该属性类型的对象, 2. 自动查找到的对象,赋值给该属性。
注意: 注解@Autowired注入的属性,可以省略属性的get和set方法。

在这里插入图片描述
@Qualifier

1. 使用: 配合@Autowired使用。
2. 含义: 在spring工厂查找符合属性类型的对象,当注入给属性时,限定要注入对象的id。

Spring注解整合Junit测试

使用步骤:

  1. 导入spring-test的jar和junit的jar。
spring-test.jar
junit.jar
hamcrest.jar
  1. 整合Spring和Junit

  2. 测试注解加载spring工厂。

@RunWith(SpringJunit4ClassRunner.class)//整合spring+Junit
@ContextConfiguration("classpath:配置文件路径")//初始化spring工厂,并且指定配置文件路径。
public class 测试类{
    
    @Test
    public void test1(){
        //指定测试的代码。
    }
}

在这里插入图片描述

SSM整合注解版本

搭建环境
1. 导入相关的jar
2. 导入相关的配置文件。
3. 初始化SSM开发环境初始化配置
	web.xml
		struts2核心控制器
		spring工厂监听器
		spring配置文件
	applicationContext.xml
		开启spring注解
			context:component-scan base-package="包1.包2.包3"
		连接池
		事务相关内容[txManager  txadvice  aop]
		mybatis整合相关: sqlSessionFactoryBean  MapperScannerConfigurer
编码
注册功能:
1.2. 实体
3. DAO接口,Mapper文件。
4. Service接口,Service实现。 交给spring工厂管理[@Service注解]
5. Action,交给spring工厂管理[@Controller注解  @Scope("prototype")]
6. 映射action的访问路径 struts.xml
	<action name="" method="" class="spring工厂中的action的id">

补充

spring集成properties配置文件。

spring引入外部properties配置文件。

<context:property-placeholder location="外部properties配置文件的路径"></context:property-placeholder>

获得properties中的值

在这里插入图片描述

坑:

1. properties配置文件中的key不要使用“username”
2. 命名规范:
	前缀.name=value
	
	applicationContext.xml
	${前缀.name}

3. spring配置文件中
	MapperScannerConfigurer中无法是使用properties配置文件中的值。
	原因: 加载时间早于properties配置文件的加载。

aop增强类型[通知类型]

MethodInterceptor 书写增强代码 环绕增强 环绕通知

特点:前置增强, 后置增强,异常位置增强。

MethodBeforeAdvice

解释:

前置增强.
使用:
public class XxxAdvice implements MethodBeforeAdvice{
   public void xxx(...){
       //代码。
   }
}

在这里插入图片描述

AfterReturningAdvice

后置增强

在这里插入图片描述>

ThrowsAdvice 异常通知。


Spring面试专题[重点]

面试技巧(3个)

案例1:

技巧1: 从实际应用的角度,把技术的本质解释说来。(绝对不能只说概念)
1. int和Integer的区别?
	int基本数据类型,默认值是0。
	Integer包装类型,对象类型,默认值是null。
	Integer可以表示null,int无法表示null,比如在做学生考试系统信息:成绩信息Integer类型(null可以表示缺考,0表示考试了0)

2. ==和equals区别?
	==:比较的变量内存储的数据: 
		基本数据类型: a == b; 比较的是字面值。
		对象类型: Person p1 = ...; Person p2 = ...;
				p1 == p2;比较的对象的地址。
	equals:  p1.equals(p2);
		方法:
			默认继承Object类的equals方法,比较地址。
			通过本类覆盖equals方法,实现比较内容的效果。

案例2:

技巧2:
·	回答技巧:
		举例子,怎么用的,就怎么说!(从实际应用角度解释)
1. 说一下你对springaop的理解?
	官方:
		AOP编程思想的实现,面向切面编程,从思想(表面),在不修改目标代码情况下,动态为其增加额外功能代码。
		SpringAOP本质:通过java技术,动态为目标类生成代理类,并且产生代理对象,替换目标对象接受调用。
		
	回答技巧:
		举例子,怎么用的,就怎么说!(从实际应用角度解释)
       面向切面编程,比如,我在做xxx项目的时候,xx功能(事务,日志,性能监控),可以在一开始不关注任何事务和日志的和性能的代码,直接写service的核心业务功能,可以通过springaop技术动态为service增加上事务,日志,性能监控,不会对原有代码产生任何修改。(示例,别背)

案例3:

技巧:如果知道技术的原因,底层原理,尽量多描述.
1. String和StringBuild的区别?
	String不可变
		不可变: "abc" "abcd" 
		① 为什么String是不可变的?(怎么实现不可变)
			final修饰,导致String不能被继承,不能通过子类的方法替换String的实现.
           String内部是使用char[]实现,且没有提供任何修改字符串内容的方法。
       ② 为什么String要设计成不可变的?
       	String有特性 串池:
       		特点: 串池中共享字符串对象,重复使用。
       		作用: 节省字符串对象重复创建消耗的时间和内存空间。(提高字符串使用效率,性能,优点)
       	避免串池在共享字符串出现线程不安全的问题.
        缺点:
        	字符串拼接。
        		"a"+"b"+"c"+"d" 产生大量的中间对象,无用对象浪费创建时间,浪费了内存空间。(效率低)
	StringBuilder可变
		优点:
			可变字符串。
			字符串拼接,可以直接在StringBuilder对象上修改。效率高。
		
2. springaop技术的理解?
	面向切面编程,
	比如。。。。。。。
	原理: 
		....
警告:
	如果不理解,别背,也别说。

SpringIOC/DI原理

SpringIOC /DI
思想: 反转控制,依赖注入,将对象创建的权利,从当前的代码中转移spring工厂中,对象属性赋值的权利转移到spring工厂中。
原理:
	工厂设计模式+反射+配置文件
	工厂设计模式:
   public class BeanFactory{
   	public Object getObject(String name){
           //根据name获得对应的全类名(properties配置文件)
           String name = ...;
           Class clazz = Class.forName(name);
           return clazz.newInstance();
   	}
   }
应用好处(使用): 解耦和
	将对象创建和属性赋值的耦合解开。
	比如开发中Service,Controller,DAO对象,连接池,事务管理器,都可以从spring工厂中获得,实现了解耦和效果。

详解:
在这里插入图片描述

SpringAOP底层实现原理

AOP思想:
	面向切面编程,在不修改目标代码的情况的情况下,动态为其增加额外功能。
SpringAOP技术:
	本质:使用了动态代理的设计模式,为目标类的代码,生成一个代理类,产生代理对象,替换目标对象接受调用。
静态代理
1. 编码
	目标对象相同的接口。
	额外功能
	拥有目标对象,调用目标对象的方法
2. 代码:
public class UserServiceProxy implements UserService{
	private UserService userService = new UserServiceImpl();
    public void regist(){
		System.out.println("前置增强");
		//调用目标对象的方法
		userService.regist();
		
		System.out.println("前置增强");
    }
}
3. 解释
	作用: 实现了事务,日志,权限,性能代码解耦和。
	缺点: 所有静态代理类,都是程序员人工编写,为每个目标类,都要书写一个代理类,代码冗余。
Jdk动态代理[基于接口的]
动态代理:
	代理类是通过代码自动生成的。
特点:
	要求目标类必须有接口。
//直接生成代。
Object proxy = Proxy.newProxyInstance(ClassLoader,目标类的接口,增强功能类);

//重要参数:
ClassLoader: 动态字节码技术,动态生成一个类信息的byte[],借助于classloader,将byte[]转化为Class对象。
目标类接口:UserService
public class Proxy0 implements UserService{
    public void regist(){
        
        //

    }
}
增强功能类: 书写额外功能,类似Spring的MethodInterceptor。
	
代理类产生过程

在这里插入图片描述

类加载

ClassLoader拥有将存储类信息的字节数组,转化为Class对象

在这里插入图片描述

JDK动态代理的代码实现
1. 目标对象
	UserServiceImpl
2. 额外功能增强的类
	InvocationHandler
3. 生成代理类
	Object proxy = Proxy.newProxyInstance(类加载器,目标类的接口,增强功能);
public static void main(String[] args) {
		//1. 准备目标对象
		final UserService us = new UserServiceImpl();
		//2。 准备额外功能
		InvocationHandler handler = new InvocationHandler() {
			/**
			 * proxy: 产生当前代理对象
			 * method: 目标对象的方法
			 * args: 目标对象的方法实际传入的参数
			 */
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				//前置额外增强
				System.out.println("前置增强....");
				//目标对象的目标方法调用
				Object o = method.invoke(us, args);//相当于mi.proceed();
				System.out.println("后置增强.....");
				//后置额外增强。
				return o;
			}
		};
		//3. 生成代理类,产生代理对象。
		Object proxy = Proxy.newProxyInstance(us.getClass().getClassLoader(), us.getClass().getInterfaces(), handler);
		System.out.println(proxy.getClass().getSimpleName());
		UserService usproxy = (UserService) proxy;
		usproxy.regist();
	}
生成的代理类的庐山真面目
获得jvm中jdk动态代理生成的类

在这里插入图片描述

静态代理
代理类核心要素
1. 与目标对象拥有相同的方法。[继承目标类,覆盖父类的方法]
2. 额外功能代码。
3. 调用目标对象的方法。
静态代理第二种实现
目标类:
public class YellowLaodaye{
	public void saleHouse() {
		System.out.println("签合同,收钱,交易过程。");
	}
}
代理类:
public class $Proxy1 extends YelloLaodaye{
	@Override
    public void saleHouse(){
    	System.out.println("1. 发广告!");
    	System.out.println("2. 看房子!");
    	System.out.println("3. 忽悠!");
    	//调用目标对象的方法。
    	super.saleHouse();
    }
}
基于继承的静态代理
cglib的动态代理
cglib动态代理技术: 生成基于继承的代理类,及其对象。
编码
编码核心要素

在这里插入图片描述

cglib动态代理的编码步骤
1. 额外功能。  InvocationHander(cglib包下)
2. 目标对象。  YellowLaoDaye yld = ...;
3. 组装生成代理类
	增强器: EnHancer
	① 绑定父类。 YellowLaoDaye.class
	② 组合额外功能。handler
	③ 生成代理类的对象。eh.create();

示例代码:
		//1. 目标对象
		final YellowLaodaye yld = new YellowLaodaye();
		
		//2. 增强功能 
		InvocationHandler handler = new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				//前置增强。
				System.out.println("1. 发广告!");
		    	System.out.println("2. 看房子!");
		    	System.out.println("3. 忽悠!");
		    	//调用目标对象的目标方法。
		    	Object obj = method.invoke(yld, args);
				return obj;
			}
		};
		//3. 组装生成代理类的对象。
		//0. 创建增强的组合器。
		Enhancer eh = new Enhancer();
		//① 绑定父类。
		eh.setSuperclass(YellowLaodaye.class);
		//② 绑定额外功能对象
		eh.setCallback(handler);
		//③ 生成代理类对象
		Object proxy = eh.create();
		//System.out.println(proxy.getClass().getSimpleName());
		
		YellowLaodaye proxylaodaye = (YellowLaodaye) proxy;
		
		proxylaodaye.saleHouse();

总结Springaop原理:

1. 本质:
	借尸还魂 移花接木 李代桃僵。
	为目标类,使用动态字节码技术(jdk动态代理,cglib动态代理)动态生成代理类,反射创建代理类的对象,替换原有的目标对象。
	注释:
		① 如果目标类有接口,spring默认会使用jdk动态代理,
		② 如果目标类没有接口,但是能够被继承(没有被final修饰),spring会自动切换使用cglib动态代理技术,
		③ 如果目标类,没有接口且被final修饰,无法完成代理类生成。
2. Jdk动态代理
	基于接口的方式生成代理类。
	要求: 目标类必须有接口。
3. Cglib动态代理
	基于继承的方式生成代理类。
	要求: 目标类必须能够被继承【不能用final修饰】
4. 补充:动态代理性能
	Jdk版本每次更新,都会大幅度提升Jdk动态代理性能,jdk1.8以后,Jdk动态代理性能完胜cglib; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值