Spring 的一些基础知识

Spring

AOP

面向切面编程,使用”横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与业务逻辑关系不大的部分是横切关注点。横切关注点经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事务管理等。

AOP基于代理模式,动态代理 :AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成aop对象.aop对象包含目标的全部方法,并在特定切点进行增强处理,然后回调原对象.

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理

动态代理

JDK动态代理是基于Java的反射机制实现的,主要涉及到java.lang.reflect包中的Proxy和InvocationHandler。

InvocationHandler是一个接口,通过实现这个接口定义一个横切的逻辑!然后通过反射机制调用目标类的方法,这样就能动态的把非业务逻辑和业务逻辑动态的拼接在一起.

proxy则利用InvocationHandler创建代理实例,来间接的调用代理的方法!

JDK的反射是基于接口的!也就是你的service一定是有接口的不然是不行的!这时候就有个Cglib可以顶上了!

Cglib采用了底层的字节码技术,为代理类创建了一个子类来代理它!

简单实现

1
2
3
4
5
6
7
8
9
10
11
@Service
public class LoginService{
if(isLegal(userId)){
System.out.println(userId + "正在登录");
return;
}
System.out.println(userId + "非法用户,禁止登录");
}
private boolean isLegal(String userId){
return !"user_1".equalsIgnoreCase(userId);
}

插入日志功能

1
2
3
4
5
6
7
8
9
10
11
12
13
@Aspect
@Comonent
public class LoginAspect{
@Arount(value = "execution(* com.universexin.LoginService.login(..))")
private Object loginAspect(ProcedingjoinPoint jp) throw Throwable{
Object[] args = jp.getArgs();
String userId=(String) args[0];
System.out.println("日志:" + userId + "开始登录");
Object result = jp.proceed();
System.out.println("日志:" + userId + "结束登录");
return result;
}
}

知识点

spring优点:低侵入,IOC低耦合,AOP对日志安全等通用应用统一管理,高复用.

IOC是什么,控制反转,让对象创建不用去new.由spring通过反射机制根据配置文件在运行时动态创建对象.spring提供4种集合配置,如:list,set,map,props(双string的map)

事务

Spring 事务传播

required:没有就创建,存在就加入

supports:存在就加入,不存在就不做事务

mandatory:存在就加入,不存在就抛异常

requires_new:不管是否存在都新建

no_supported:如果存在事务将事务挂起.

nerver:存在事务我就抛异常.

nested:存在就嵌套,不存在就创建

事务隔离级别:

default:默认db级别

read_uncommitted:读取未提交(会脏读),基本不用

read_committed:读取已提交(会幻读,不可重复读)

repeatable_read:可重复读,行锁(会幻读)

serializable:完全看不到其他事务的操作,表锁

解释Spring支持的几种bean的作用域。

1
2
3
4
5
6
Spring框架支持以下五种bean的作用域:
singleton : bean在每个Spring ioc 容器中只有一个实例。
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean,该作用域仅在基于web的 Spring ApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

Spring实现原理

Spring是实现了工厂模式的工厂类。这个类名为BeanFactory(实际上是一个接口),在程序中通常BeanFactory的子类ApplicationContext。Spring相当于一个大的工厂类,在其配置文件中通过元素配置用于创建实例对象的类名和实例对象的属性。

IOC,IOC就是一个容器,负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。很好地实现模块之间的解耦,@Autowired,不用每次去new service。

AOP面向切面,如:系统中有很多各不相干的类的方法,在这些众多方法中要加入某种系统功能的代码(是否能理解是类似于中间件),例如,加入日志,加入权限判断,加入异常处理,Transactions事务,Synchronization同步

实现AOP功能采用的是代理技术,客户端程序不再调用目标,而调用代理类,代理类与目标类对外具有相同的方法声明,有两种方式可以实现相同的方法声明,一是实现相同的接口,二是作为目标的子类。

Spring框架的好处

容器:Spring 包含并管理应用中对象的生命周期和配置。

MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。

事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。

异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。

ApplicationContext通常的实现是什么?

FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。

ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。

WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean。

什么是Spring beans

​ Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中 的形式定义。

​ Spring 框架定义的beans都是单件beans。在bean tag中有个属性”singleton”,如果它被赋为TRUE,bean 就是单件,否则就是一个 prototype bean。默认是TRUE,所以所有在Spring框架中的beans 缺省都是单件。

Spring框架中bean的生命周期

Spring容器从XML 文件中读取bean的定义,并实例化bean

Spring根据bean的定义填充所有的属性

如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法;

如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。

如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。

如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。

如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。

如果bean实现了 DisposableBean,它将调用destroy()方法。

SpringMVC的原理

Spring MVC的核心就是 DispatcherServlet , 一个请求经过 DispatcherServlet ,转发给HandlerMapping ,然后经反射,对应 Controller及其里面方法的@RequestMapping地址,最后经ModelAndView和ViewResoler返回给对应视图 。

SpringMVC的原理图10191011

springmvc拦截器的定义和配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//测试拦截器1
public class HandlerInterceptor1 implements HandlerInterceptor{

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {

System.out.println("HandlerInterceptor1....preHandle");

//false表示拦截,不向下执行;true表示放行
return true;
}

@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {

System.out.println("HandlerInterceptor1....postHandle");

}

@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {

System.out.println("HandlerInterceptor1....afterCompletion");
}
}
  1. preHandle方法:进入Handler方法之前执行。可以用于身份认证、身份授权。比如如果认证没有通过表示用户没有登陆,需要此方法拦截不再往下执行(return false),否则就放行(return true)。
  2. postHandle方法:进入Handler方法之后,返回ModelAndView之前执行。可以看到该方法中有个modelAndView的形参。应用场景:从modelAndView出发:将公用的模型数据(比如菜单导航之类的)在这里传到视图,也可以在这里同一指定视图。
  3. afterCompletion方法:执行Handler完成之后执行。应用场景:统一异常处理,统一日志处理等。

BeanFactory和ApplicationContext有什么区别?

    BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

(1)BeanFactory:是Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。ApplicationContext接口作为BeanFactory的派生,除了提供BeanFactory所具有的功能外,还提供了更完整的框架功能:

①继承MessageSource,因此支持国际化。

②统一的资源文件访问方式。

③提供在监听器中注册bean的事件。

④同时加载多个配置文件。

⑤载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

①BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。
②ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

③相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

(3)BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。

(4)BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。

Autowired与Resource

使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在Spring配置文件进行配置,<context:annotation-config />。在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。在使用@Autowired时,首先在容器中查询对应类型的bean:

如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;

如果查询的结果不止一个,那么@Autowired会根据名称来查找;

如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。

@Autowired可用于:构造函数、成员变量、Setter方法

注:@Autowired和@Resource之间的区别

(1) @Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。

(2) @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。

来源

https://blog.csdn.net/a745233700/article/details/80959716