What Have Learn About Spring
[Spring summary]
Spring 解决什么问题
- 类之间的依赖
不同类之间利用实例化对象传递功能方法,在每次创建对象时候,都会产生一段耦合代码。
- 控制事物繁琐
每次事物的控制都需要冗杂的try-catch
代码块来,可以使用AOP(Aspect Oriented Programming)思想的具体实现来解决
- 框架的引入复杂
每个框架的单独引入比较乱,需要一个对其他框架的接入接口式的的管理。
-
Spring 解决了什么
-
Spring 能帮我们低侵入/低耦合地根据配置文件创建及组装对象之间的依赖关系。IoC
-
Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制等。AOP
-
Spring 能非常简单的且强大的声明式事务管理。AOP TX
-
Spring 提供了与第三方数据访问框架(如Hibernate、JPA)无缝集成,且自己也提供了一套 JDBC 模板来方便数据库访问。
-
Spring 提供与第三方 Web(如 Struts1/2、JSF)框架无缝集成,且自己也提供了一套 Spring MVC 框架,来方便 Web 层搭建。 SSM
-
Spring 能方便的与如 Java Mail、任务调度、缓存框架等技术整合,降低开发难度。
-
Spring 有什么
Spring主要是一个容器,里面装了一些对象(比如SqlSessionFactory之类的可以被公用),然后大家可以随取随用。
实现IOC思想来创建对象放在容器内,实现DI思想来建立对象之间的关系
IOC思想:Inversion Of Control,控制权的转移,把创建对象的权力转移给容器来控制
Spring容器通过配置文件配置的内容,利用反射操作创建出需要的对象,把这些对象放在Spring容器中,随时用。
<!-- 第一步!配置文件中配置自己想要什么对象(Bean豆子) -->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
<property name="username" value="${jdbc.username}"/>
</bean>
<!-- 可以在编写的类上面加注解,Spring会自动扫描出来,初始化创建一个豆子 -->
@Service
public class AccountServiceImpl implements IAccountService {}
<!-- 第二步!在代码中可以通过注解拿对象(豆子),也可以把Spring容器拿到手从里面取 -->
public class UserController {
@Autowired
private IUserService userService;
}
DI思想:Dependency Injection,依赖注入,把对象的关系连接起来!
举例:容器帮我们创建A对象和B对象,我们想把B对象设置为A对象的一个字段值,A和B就有一个赋值的依赖关系,DI思想就是要连接起来对象的这种关系。Spring容器就通过取值与赋值把对象连接起来
<!-- 第一种!配置文件中往豆子里注入值 -->
<!-- dataSource豆子 -->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
<property name="username" value="${jdbc.username}"/>
</bean>
<!-- 事务管理器豆子,把dataSource豆子拿过来做属性值-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<!-- 注入!-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 第二种!通过注解,从容器中拿取豆子,同上 -->
public class UserController {
@Autowired
private IUserService userService;
}
实现AOP思想来解决事物等繁琐代码
AOP(Aspect Oriented Progranmming)
AOP是面向切面编程,把操作分层,分清主次等层次。
//有事务管理的数据库操作可以分为四层
try {
//1: start transaction
transactionManager.startTransaction();
//2: do the main job
userService.addAUser(user);
//3: commit transaction
transactionManager.commitTransaction();
} catch (Exception e) {
//4: rollback the transaction
transactionManager.rollbackTransaction();
}
通过把操作分层,我们可以筛选出我们感兴趣的主操作(第二步)和事物等其他的为主操作服务的操作。可以利用AOP思想,把操作分层,然后为主操作类(Service类)来创建代理类来减少主操作种的代码量,专心写主操作中的代码
自我理解:AOP的切面可以被理解为一层操作,每次请求/操作都可以被分成多层切面。
静态代理和动态代理来实现AOP思想
- 静态代理
自我理解:为需要添加其他操作的Service方法(主操作)编写一个代理类方法,代理方法就像汉堡,把精华部分(主操作)和为精华服务的部分(事物管理、日志记录等)分层起来。
-
动态代理
-
The same as 静态代理
每一个需要代理的Service类生成一个代理,代理的内容就是添加为主操作其他的操作。 -
The differences from 静态代理
自动生成的,要接受主顾的接口信息,看看需要代理哪些方法。
自动生成的,为每一个主顾生成的代理(生产的汉堡包)除了主操作都一样
不确定谁要代理,在 运行时候生成代理。
-
自我理解:有太多需要代理的主操作了,他们需要的代理都是简单的添加事物操作,那么我就可以重构了,接收类的接口信息,为它的每一个方法添加事物操作,组成一个代理类来用。
上面只是理解,静态代理是自己写的,动态代理需要实现InvocationHandler写一个代理类的模板类,利用Proxy类拿取动态代理类。静态代理是一个手工汉堡包,可以吃的那种。动态代理类通过看源码我理解为是一个空壳子,所有人得到的只是一套餐具,吃的是同一个汉堡包(代理类的模板类的invoke方法)。
Spring 操作AOP
Spring中的AOP实现单位为方法,每个需要加工成汉堡包的肉片(方法)被称为joinPoint,所有待加工成汉堡包的肉片(方法)组成pointCut。需要的菜叶和面包片(事物、日志等对主操作的增强)成为advice,pointCut和advice组装成多个汉堡包,汉堡包叫aspect(切面)。(我觉得joinPoin和advicet才应该叫切面,可不知为什么汉堡包才叫切面。
AOP切面可以在Spring容器的配置文件中配置,也可以通过注解定义一个切面类
<!-- AOP配置 -->
<aop:config>
<!-- 插入管理事务的joinPoint -->
<aop:aspect ref="myTransactionManager">
<aop:pointcut
expression="execution(* com.gasin.spring.service.impl.*ServiceImpl.addAUser(..))"
id="transactionPointcut" />
<aop:around method="arountTransaction" pointcut-ref="transactionPointcut"/>
<!-- <aop:before method="startTransaction" pointcut-ref="transactionPointcut" />
<aop:after-returning method="commitTransaction" pointcut-ref="transactionPointcut"/>
<aop:after-throwing method="rollbackTransaction" pointcut-ref="transactionPointcut"/> -->
</aop:aspect>
<!-- 插入记录ERROR的切面 -->
<aop:aspect ref="errorLogUtil">
<aop:pointcut expression="execution(* com.gasin.spring.service.impl.*ServiceImpl.updateAUser(..))" id="errorNotePointCut"/>
<aop:after-throwing method="noteAError" pointcut-ref="errorNotePointCut" throwing="e"/>
</aop:aspect>
<!-- 插入方法运行的切面 -->
<aop:aspect ref="writeMethodLog">
<aop:pointcut expression="execution(* com.gasin.spring.service.impl.*ServiceImpl.updateAUser(..))" id="errorNotePointCut"/>
<aop:before method="writeMethodLog" pointcut-ref="errorNotePointCut" />
</aop:aspect>
</aop:config>
<!-- spring配置文件中AOP注解解析器 -->
<aop:aspectj-autoproxy/>
@Component
@Aspect
public class MyTransactionManager {
/* 贴上的注解value为AspectJ语句*/
@Pointcut("execution(* com.gasin.spring.service.impl.*ServiceImpl.addAUser(..))")
public void transactionPointAsPect(){}
/**
* Around方法
*/
@Around("transactionPointAsPect()")
public void arountTransaction(ProceedingJoinPoint pjp) {
try {
startTransaction();
pjp.proceed();
commitTransaction();
} catch (Exception e) {
rollbackTransaction();
} catch (Throwable e) {
e.printStackTrace();
}
}
/**
* 开启事物
*/
@Before("transactionPointAsPect()")
public void startTransaction() {
}
/**
* 提交事物
*/
@After("transactionPointAsPect()")
public void commitTransaction() {
}
@AfterReturning("transactionPointAsPect()")
public void afterReturnTransaction() {
}
/**
* 回滚事物
*/
@AfterThrowing("transactionPointAsPect()")
public void rollbackTransaction() {
}
}
Spring 引入其他框架
我还不太了解这相关的知识,等着自己慢慢学。
over
by wangyk