Spring注解的原理和使用
注解(Annotation)提供了一种安全的类似注释的机制,为在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解来使用这些数据),用来将任何的信息或者元数据与程序元素(类、方法、成员变量等)进行关联。其实就是更加直观更加明了的说明,这些说明信息与程序业务逻辑没有关系,并且是供指定的工具或框架使用的。Annotation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的申明语句中。
Annotation其实是一种接口。通过Java的反射机制相关的API来访问Annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。Java语言解释器在工作时会忽略这些Annotation,因此在JVM中这些Annotation是“不起作用”的,只能通过配套的工具才能对这些Annotation类型的信息进行访问和处理。
Annotation和interface的异同:
1、 annotition的类型使用关键字@interface而不是interface。它继承了java.lang.annotition.Annotition接口,并非申明了一个interface。
2、 Annotation类型、方法定义是独特的、受限制的。Annotation类型的方法必须申明为无参数、无异常抛出的。这些方法定义了Annotation的成员:方法名称为了成员名,而方法返回值称为了成员的类型。而方法返回值必须为primitive类型、Class类型、枚举类型、Annotation类型或者由前面类型之一作为元素的一位数组。方法的后面可以使用default和一个默认数值来申明成员的默认值,null不能作为成员的默认值,这与我们在非Annotation类型中定义方法有很大不同。Annotation类型和他的方法不能使用Annotation类型的参数,成员不能是generic。只有返回值类型是Class的方法可以在Annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
3、 Annotation类型又与接口有着近似之处。它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
* 元注解@Target,@Retention,@Documented,@Inherited
*
* @Target 表示该注解用于什么地方,可能的 ElemenetType 参数包括:
* ElemenetType.CONSTRUCTOR 构造器声明
* ElemenetType.FIELD 域声明(包括 enum 实例)
* ElemenetType.LOCAL_VARIABLE 局部变量声明
* ElemenetType.METHOD 方法声明
* ElemenetType.PACKAGE 包声明
* ElemenetType.PARAMETER 参数声明
* ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
*
* @Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:
* RetentionPolicy.SOURCE 注解将被编译器丢弃
* RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
* RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
*
* @Documented 将此注解包含在 javadoc 中
*
* @Inherited 允许子类继承父类中的注解
对SpringIOC的理解
IOC、DI:
java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用他的合作对象时,自己均要使用像new object() 这样的语法来完成合作对象的申请工作。你会发现:对象间的耦合度高了。而IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。对象只需要关系业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC,DI)。
DI其实就是IOC的另外一种说法。DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。
SpringBoot集成AOP
两个步骤:
- 添加的Jar依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、定义AOP类
SpringMVC中自定义AOP的配置
1、需要的jar包依赖:
(实际的使用中jar适用的版本请自行根据实际情况配置,这里演示的Spring 的版本是4.3.6)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
2、在XML配置文件中添加:
<!-- 开启AOP拦截 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!—配置自定义的AOP切面类的包扫描路径和aop的适用范围 -->
<context:component-scan base-package="com.aop.**">
<!-- aop 使用的范围 -->
<context:include-filter type="annotation" expression="com.web.TestController"/>
<!—需要对多个类添加AOP就写多个 -->
<context:include-filter type="annotation" expression="com.web.TestController2"/>
</context:component-scan>
3、定义切面类 示例
Spring编程式事务
在 Spring 出现以前,编程式事务管理对基于 POJO 的应用来说是唯一选择。比如使用Hibernate 的时候,需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。(或者是列举JDBC的例子)通过 Spring 提供的事务管理 API,我们可以在代码中灵活控制事务的执行。在底层,Spring 仍然将事务操作委托给底层的持久化框架来执行。
Spring事务相关的最重要的三个接口
TransactionDefinition 给定的事务规则,定义如隔离级别、传播行为等
PlatformTransactionManager 事务管理器
TransactionStatus 用于表示一个运行着的事务的状态
事务的传播属性的设置:
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
Spring通知的五中类型
Before-在方法被调用之前调用通知。
After-在方法被调用之后调用通知,无论方法是否执行成功。
After-returning-在方法成功执行之后调用通知。
After-throwing-在方法抛出异常后调用通知。
Around-方法被调用之前和调用之后各执行一次自定义的行为,通知把被通知方法“包裹”起来了。
Spring的handlerMapping的机制:
HandlerMapping 在这里起到路由的作用,负责找到请求的Controller。
Spring MVC 默认提供了4种 HandlerMapping的实现
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
通过配置请求路径和Controller映射建立关系,找到相应的Controller
org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping
通过 Controller 的类名找到请求的Controller。
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
通过定义的 beanName 进行查找要请求的Controller
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
通过注解 @RequestMapping("/userlist") 来查找对应的Controller。