@RestController
public class MyController {
@Resource
private MyService myService;
public void doRequest(HttpServletRequest request) {
// 做请求
myService.doService(request);
}
}
public interface MyService {
}
@Service
public class MyServiceImpl implements MyService {
}
spring ioc:在tomcat启动的时候先启动spring容器,根据xml配置,或者是你的注解,去实例化你的一些bean对象,然后根据xml配置或者,去对bean对象之间的引用关系,去进行依赖注入。
底层核心就是反射,他会通过反射的技术,直接根据你的类去构建对应的对象出来。spring ioc,系统的类与类之间彻底的解耦合。
@Service
public class MyServiceA {
public void doServiceA() {
// 开启事物
// insert
// update
// update
// delete
// 如果有任何一个语句失败了,回滚事物
// 如果大家都成功了,提交事物
}
}
@Service
public class MyServiceB {
public void doServiceB() {
// 开启事物
// update
// update
// insert
// 如果有任何一个语句失败了,回滚事物
// 如果大家都成功了,提交事物
}
}
Spring AOP,可以做一个切面。在类似于MyServicexxx这种类,在这些类的方法中,都去织入一些代码,在所有这些方法刚开始运行的时候,都先去开始一个事物,在所有方法运行完毕之后,去根据是否异常抛出来判断,如果抛出异常,就回滚事物,如果没有异常就提交事物。
Spring在运行的时候,使用动态代理技术。
public class ProxyMyServiceA {
private MyServiceA myServiceA;
public void doServiceA() {
// 开启事物
//直接取调用我一来的MyServiceA 对象方法
myServiceA.doServiceA();
// 根据他是否抛出来提交事物或者回滚事物
}
}
/**
* @author finen
* 把这个类声明为一个切面:需要把该类放入到IOC容器中,在声明为一个切面
* 可以使@Order注解指定切面优先级,优先级值越小优先级越高
*/
@Order(2)
@Aspect
@Component
public class LoggingAspect {
/**
* 定义一个方法:用于声明切入点表达式,一般地,该方法中不需要切入其他的的代码
* 使用@Pointcut来声明切入点表达式
* 后面的其他通知直接使用方法名引用当前切入点表达式
*/
@Pointcut("execution(public int top.finen.spring.aop.impl.ArithmeticCalculator.*(int, int))")
public void declareJoinPointExpression() {}
/**
* 声明该方法是一个前置通知:在目标方法之前执行
* 在声明能获取到执行的参数
* @param joinPoint
*/
@Before("declareJoinPointExpression()")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " begins with:" + args);
}
/**
* 后置通知:在目标方法执行后(无论是否发生异常),执行的通知
* 在后置通知中还不能访问目标方法执行的结果。
* @param joinPoint
*/
@After("declareJoinPointExpression()")
public void afterMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method " + methodName + " end");
}
/**
* 在方法结束受执行代码的之后返回的通知
* 返回通知是可以访问到方法的返回值的
* @param joinPoint
*/
@AfterReturning(value = "declareJoinPointExpression()",
returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method " + methodName + " end with: " + result);
}
/**
* 在方法出现异常时,会执行的代码
* 可以访问到异常对象,且可以指定出现特定异常时在执行通知代码。
* @param joinPoint
* @param exception
*/
@AfterThrowing(value = "declareJoinPointExpression()",
throwing = "exception")
public void afterThrowing(JoinPoint joinPoint, Exception exception) {
String methodName = joinPoint.getSignature().getName();
System.out.println("The method " + methodName + " throwing with: " + exception);
}
/**
* 环绕通知需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 环绕通知必须有返回值,且返回值为目标方法的返回值
* @param proceedingJoinPoint
*/
@Around("declareJoinPointExpression()")
public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) {
Object result = null;
String methodName = proceedingJoinPoint.getSignature().getName();
//执行目标方法
try {
//前置通知
System.out.println("The method " + methodName + " begins with:" + Arrays.asList(proceedingJoinPoint.getArgs()));
result = proceedingJoinPoint.proceed();
//返回通知
System.out.println("The method " + methodName + " end with:" + result);
} catch (Throwable throwable) {
//异常通知
System.out.println("The method " + methodName + " throwing with: " + throwable);
throwable.printStackTrace();
}
//后置通知
System.out.println("The method " + methodName + " end");
return result;
}
}
就是动态的创建一个代理类出来,创建这个代理类的实例对象,在这个里面引用你真正自己写的类,所有方法的调用,都是先走代理类的对象,他负责做一些代码上的增强,再去调用你写的那个类。
如果你的类是实现了某个接口的,spring aop会使用jdk动态代理,生成一个跟你实现同样接口的一个代理类,构造一个实例对象出来,jdk动态代理是在你的类有接口的情况下生成的。
很多时候,某各类可能没有实现接口,spring aop会改用cglib来生成动态代理,他是生成你的类的一个子类,他可以动态生成字节码,覆盖你的一些方法,再发方法里加入增强的代码。
Spring容器中的bean可以分为5个范围:
- singleton:默认,每个容器只有一个bean实例
- prototype:为每个bean请求提供一个实例
- request:为每个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
- session;与request范围类似,确保每个session有一个bean的实例,在session过期后,bean会随之失效。
- global-session:
@RestController
public class MyController {
@Resource
private MyService myService;
public void doRequest(HttpServletRequest request) {
// 做请求
myService.doService(request);
}
}
public interface MyService {
}
@Service
public class MyServiceImpl implements MyService {
public void doService() {
// 访问数据库
}
}
不可能线程安全的,每一次请求调用都会到一个bean中。通常在一些bean中很少会有实例变量的。通常都是访问数据库的。
事物实现原理,事物的传播机制。如果你加了一个@Transactional
注解,此时spring就会使用AOP思想,对你的这个方法在执行之前,先去开启事物,在你的任务执行结束,再去提交事物。
@Transactional(propagation = Propagation.REQUIRED)
public void doServiceA() {
// 开启事物
//直接取调用我一来的MyServiceA 对象方法
myServiceA.doServiceA();
// 根据他是否抛出来提交事物或者回滚事物
}
- Propagation.REQUIRED:如果当前没有事物,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
- Propagation.SUPPROTS:支持当前事物,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
- Propagation.MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就跑出异常。
- Propagation.REQUEST_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
- Propagation.NOT_SUPPORTED:以非实物方式执行操作,如果当前存在事务,就把当前事务挂起。
- Propagation.NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- Propagation.NESTED:如果当前存在事务,则嵌套事务内执行,如果当前没有事务,则按REQUIRED属性执行。
- 1.实例化Bean
- 2.设置对象属性(依赖注入)
- 3.处理Aware接口,Spring会检测对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给Bean。示例:如果一个Bean实现了ApplicationContextAware接口,Spring容器就会调用我们的Bean的setApplicationContext(ApplicationContext)方法,传入Spring上下文,把Spring容器传递给bean。
- 4.BeanPostProcessor:如果想对bean进行自定义的处理,那么可以让Bean显示BeanPostProcessor接口,那么它将会调用postProcessBeforeInitialization(Object obj, String s)方法。
- 5.InitializingBean与init-method
- 6.执行
- 7.DisposableBean:当bean不需要的时候,会经过清理阶段,如果bean实现了DisposableBean接口,会调用其实现的destroy方法。
- 8.destroy-method:如果这个bean的spring配置中配置了destory-method属性,会自动调用其配置的销毁方法。
1.tomcat的工作线程将请求转交给Spring mvc框架的DispatcherServlet
2.DispatcherServlet查找@Controller注解的controller类,一般会给controller类加上@RequestMapping注解,标注说明那些controller用来处理那些请求。根据请求的url定位走到那个controller来处理。
3.根据@RequestMapping去查找,使用这个Controller内的那个方法来进行请求的处理,对每个方法一般也会加@RequestMapping注解
4.调用某个controller内的方法来进行处理。
5.controller方法会有一个返回值(json)