spring 基础

 

spring的核心思想是 控制反转 和 切面编程

而其中控制反转的 实现是 依赖注入,控制反转是 一种通过描述 (在Java中可以是XML或者 注解 )并通过第三方去产生或获取特点对象的方式。第三方是 IOC容器

 https://www.zhihu.com/question/23277575

 

 

spring IOC容器的设计是基于两个接口:

BeanFactory 

ApplicationContext 一般使用这个,三个常用实现类

  1. ClassPathXmlApplicationContext 他可以加载类路径下的配置文件,要求诶之问价您必须在类路径下,不在的话,加载不了
  2. FileSystemXmlApplicationContext 它可以加载磁盘任意路径下的配置文件(必须有访问权限)
  3. AnnotationConfigApplicationContext 注解

 

ApplicationContext和BeanFactory另一个最大的不同之处在于:前者会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor,InstantitationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动将它们注册到应用上下文中,而后者需要在代码中通过手工调用addBeanPostProcessor方法进行注册。

这也是在实际在使用ApplicationContext的原则之一。

 

父子容器

通过HierarchicalBeanFactory接口,spring的IOC容器可以建立父子层级体系,子容器能访问父容器,但父容器不能访问子容器

 

Bean的初始化分为三步:

  1. Resource定位
  2. BeanDefinition的载入
  3. BeanDefinition的注册

 

Bean的生命周期

 

 

 装配Bean

 

bean之间的关系

继承 abstract, parent

依赖 depends-on

引用 ref

 

一个bean

依赖注入,为bean注入属性

<bean id="name" class="Object" >
//构造函数注入
<constructor-arg index="0" value="lin" />
//setter注入 <property name="age" value="12"/> <bean/>

第三种注入方式是 接口注入,可以注入外部资源

 

装配bean

通过XML文档装配bean,利用 ref 属性 引用 同一个文档的其他 bean。

通过XML文档,装配集合属性 <list> <map> <props> <set>

命名空间装配,c: 结构体属性声明赋值 ;p: 基本属性声明赋值 ; util: 创建集合 ,需要引用命名空间文档

 

通过注解的方式装配bean

组件扫描:@ComponentScan   @Component

自动装配 :@Autowired     (ByName -  > ByType -  > Constructor -  > Method 3.0丢弃 )

 

自动装配的歧义性:@Qualifier(指定bean的id) @Primary

 

装载带有参数的构造类 使用的是@Autowired

 

在配置类上@Configuration,使用@Bean

 

注解自定义的bean初始化,消耗方法,

@Bean的属性 initMethod destroyMethod

 

装配的混合使用

@Import 导入配置类

@ImportResource 导入外部的XML文档

 

Java的装配注解

@Named(源于java依赖注入规范) = @Component 

@Inject(源于java依赖注入规范)  = @Autowired

 

 

bean的作用域 scope属性 @scope默认是单例模式

singleton prototype

request session globalSession

 

profile

@Profile 设置在配置类上,及@Configuration修饰的类上 ,或者注解在@Bean修饰的方法上

@ActiveProfiles 激活某种环境,dev ,prop ,test 等,修饰在启动类上

 

xml文档的标签也拥有profile 属性

JVM参数 设置profile ,JAVA_OPTS="-Dspring.profiles.active=test"

 

加载属性文件properties

@PropertySource(value={} ,ignoreResourceNotFound=true,encoding) 注入外部的资源文件

Environment类解析

PropertySourcesPlaceholderConfigurer类,作用是让spring能够解析属性占位符

@Value("${jdbc.datasource.driver}") 引用属性文件的值

 

使用xml方式加载属性文件

<context:property-placeholder /> 标签

 

多条件加载bean

@Conditional 条件化注入类,而这个类需要继承Condition接口,而Profile注解的底层就是用这个注解实现的。

 

@Conditional({myClass.class})  myClass.class 继承Condition接口 ,这个注解修饰在配置类的方法上,或者配置类

 

使用EL表达式

 @Value("${}") 读取属性文件

@Value("#{}")  使用EL表达式,使用的是#

引用类的静态方法或常量  @Value("#{T(java.lang.Math).PI}")

 

切面编程

 

 概念:

连接点Joinpoint:一个类或者一段程序代码执行到具有分界性质的点

切点Pointcut:具体 就是某个类的 某个方法

增强Advice:在连接点处加入的一段代码片段

切面Apspect:切点和增强的组合

代理:一个类被AOP织入增强后,由原类和织入类混合成的代理类

引介:一种特殊的增强

织入:生成代理对象的过程,spring会根据切点方法是否有接口,使用那种代理方式,有接口使用JDK代理,没有接口使用CGLib代理

 

AOP实现的底层技术:Java反射(面向接口的JDK代理) 和 CGLib代理

 

增强类型:before前置,after后置,around环绕;afterThrowing异常抛出,afterReturing返回通知

 

spring对AOP的支持,springAOP是一种基于方法拦截的AOP,换句话说,spring只能支持方法拦截的AOP

spring有4种方式去实现AOP的拦截功能。

使用ProxyFactoryBean和对于的接口实现AOP

使用XML文档配置AOP

使用@AspectJ注解驱动切面 常用

使用AspectJ注入切面

 

注解步骤

1 选择切点,选择某个类的某个方法

2 创建切面,对于动态代理概念而言,它就如同一个拦截器,使用@AspectJ注解一个类,就代表一个切面

3 连接点 ,5个通知类型,

@After("execution * com.org.src.Myclass.println(..)") public void after(){}

execution 代表执行方法的时候会触发,* 代表任意返回类型 类的全限定名,println拦截方法的名称,(..) 任意的参数

简化形式

@Pointcut("execution * com.org.src.Myclass.println(..))") public void print(){}

@Before("print()") public void before(){}

 

4 测试AOP

@EnableAspectJAutoProxy 修饰配置类,返回一个切面

<aop:aspectj-autoproxy

 

5 给通知传递参数

@After("execution * com.org.src.Myclass.println(..))" + "&&args(name)") public void after(String name){}

注意传递的参数一定是切点方法prinln的参数

 

6 引入@DeclareParents

 

spring和数据库编程

配置数据库资源的方式

  1. spring提供了一个简单的数据源类 SimpleDriverDataSource ,可以生成一个bean
  2. 使用第三方数据池,比如DBCP,使用dbcp.BasicDataSource
  3. 使用JNDI数据库连接池,如在Tomcat,Weblogic等Java EE服务器上配置了数据库,这时数据库存在一个JNDI名称,spring提供了一个类JndiObjectFatctoryBean 类

 

配置数据库源之后,就可以配置jdbcTemplate 模板

 

jdbcTemplate执行 普通的增删改查

执行多条SQL语句,jdbcTemplate.execute() 方法,它允许 传递 ConnectionCallBack , StatementCallBack 等接口进行回调,这些接口能获取 connection ,statement 对象

 

spring-mybatis组合

配置SqlSessionFactory 的bean, 引用数据库

使用@Reposity注解所以的Mapper接口

配置MapperScannerConfigurer 的bean,属性basePackage=扫描mapper接口所在的层,另外的一个属性引用sqlsessionfactorybean。

 

spring数据库 事务管理

 

spring 使用 platformTransactionManager 接口 管理事务,创建事务,提交和 回滚。

mybatis使用的实现类是 DataSourceTransactionManager , 而 hibernate 使用的是 HibernateTransactionManager

 

XML配置数据库事务管理器,需要引入事务命名空间,创建bean,需要引用数据源。

 

Java代码方式,配置类 实现 TransactionManagerConfigurer 接口,实现 annotationDrivenTransactionManager 方法,这个方法返回的事务管理器。

同时配置类 需要 开启事务 @EnableTransactionManagement

 

以后再spring上下文中 使用 @Transactional  ,spring就知道使用的事务管理器。

 

编程式事务

 

 

使用的是TransactionDefinition 接口,用的是DefaultTransactionDefinition 实现类,使用自定义的事务类,配合事务管理器有 使用者 控制事务的提交。

 

声明式事务

 <tx :annotation -driven transaction-manager=" " />

 

@Transaction 常用的属性 isolation 隔离级别  propagation传播行为 timeout

 

spring定义的隔离级别有 5 种, 传播行为有 7种

spring的默认隔离级别是根据数据库的隔离级别变化的级别

 

传播行为常用的 有 默认REQUIRED 调用方法时,如果不存在当前事务,那么创建事务,如果之前已经存在事务了,那么就沿用之前的事务。

; REQUIRES_NEW 无论当前是否存在事务,方法都会在新的事务中运行

; NESTED 嵌套事务,如果方法抛出异常,只在自己的事务回滚,不会再主方法回滚。

 

@Transaction失效问题

因为transaction底层是AOP实现的,AOP的底层又是动态代理。

这就意味着 静态方法,类,或者 非public 方法,@Transaction是失效的。

如果public 方法内部调用了自身,@Transaction也是失效的。

 

 

springMVC

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web.html

两个配置文件,一个是web.xml文件

<web-app>

<!--配置ContextLoaderListener初始化IOC容器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置spring IOC配置文件路径 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/app-context.xml</param-value> </context-param> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> <!-- 拦截请求路径--> </servlet-mapping> </web-app>

 

第二步

与上面 web.xml 中的 <servlet-name> 元素配置的 app对应,这是 Spring MVC 的映射配置文件(xxx-servlet.xml),加载位置/WEB-INF/app-servlet.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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example.web"/>
    <bean id="resolve" class="InternalResourceViewResolver p:prefix="WEB-INF/jsp" p:suffix=".jsp"/>
    <!-- ... -->

</beans>

 

 

使用的注解

@Controller

@RequstMapping

@ResponseBody  

@RequestParam

 @SessionAttribute 从session中获取数据

@PathVariable 从URL获取参数

@RequestBody 接收JSON数据,以POJO形式; 接收JSON数组数据,转换成Java集合类型

 

重定向:redirect

 重定向后,不能保存传递对象,MVC提供了一个flash属性,RedirectAttribute re,re.addFlashAttribute() 保存传递对象。原理,它会把数据保存在session中。

 

保存并获取属性参数

@RequestAttribute

@SessionAttribute 获取session数据

@SessionAttributes 标注类,保存数据到session中

 

@CookieValue

@RequestHeader

从cookie,header获取请求信息

 

3.0之后,使用Java代码的形式,代替web.xml文件

一个初始化类,实现WebApplicationInitializer接口

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration,加载配置类
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

 

@EableWebMvc 注解修饰配置类,代表启动MVC的框架,相当于xx-servlet.xml文件

 

拦截器

自定义的拦截器 HandlerInterceptor接口,MVC提供了一个公共拦截器 HandlerInterceptorAdapter类

 

验证表单

spring 提供了对bean功能的校验,通过注解@Valid 表明那个bean 需要启动注解式的验证

JSR303注解

注解 功能
@Null  /@NotNull  
@AssertTrue /@AssertFalse 注解的元素必须为true,false
@Min @Max(value)  
@DecimalMin  @DecimalMax(value)  
@Size(max,min) 数的范围
@Digits(integer,fraction) 一个数字,值在接受范围内
@Past @Future  
@Pattern  

 

 

数据模型

Model数据模型接口

BindingAwareModelMap 类,派生出了 ExtendedModelMap类,此类又派生了ModelMap

 

视图View模型

ModelAndView

ViewResolver 接口

 

文件上传

MultipartResolver接口

实现类StandardServletMultipartResolver类,不依赖第三方包

 

表单属性form enctype="multipart/from-data"

MultipartFile接口, 也是一个文件,它是mvc提供的类

控制器上的接口可以是该类型,这个类型的接口数据有获取文件信息的方法,而保存数据的方法为transferTo

Part 

Part 是servlet提供的类,用法和文件类似,也是接受文件对象。

 

文件下载

通过HttpServletResponse 设置  响应头信息,和获得输出流对象response.getOutputStream() 。

将文件或者图片信息 写入输出流。

 

 数据转换和格式化

HttpMessageConverter   Converter 

 

格式化器  Formatter接口

@DateTimeFormat

@NumberFormat

 

为控制器添加通知

@ControllerAdvice 标注在类上,处理所有@RequestMapping方法的错误异常,属性basePackages={ 通知的控制类 }

 

以下注解标注在@ControllerAdvice 修饰类的方法上

@ExceptionHandler 某个异常类处理器,注册一个控制器异常

@InitBinder 是一个允许构建POJO参数的方法,允许构造控制器参数时,加入一定的自定义控制

@ModelAttribute 针对数据模型的注解,先于控制器运行,当标注方法返回对象时,保存到数据模型

 

处理异常的其他机制

默认情况下,spring将异常转换成合适的状态码,通过状态码确定异常发生的原因,找到对应的问题

异常隐射码类HttpStatus

 

@ResponseStatus(code=HttpStatus.XXX ,reason="NOT FOUND")

public class RException extends RuntimeException{


}

使用

@ResponseStatus注解 为自定义的异常类加上映射码
在控制器controller中 增加 处理异常类的方法,方法前用上@ExceptionHandler

 

国际化

LocaleResolver接口  解析国际化

拥有4个实现类

 

posted @ 2020-09-30 23:19  lfcom  阅读(196)  评论(0编辑  收藏  举报