
就是通过反射 + 动态代理实现!

记住它们会出现什么情况(脏读,虚读,不可重复读)。

大多数使用required,记住required的理念。
最常用的set注入。
构造器注入。
命名空间p或者c注入。
见:https://blog.csdn.net/IT_Holmes/article/details/121818148
aop配置文件的两种形式:
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="serviceTest" class="com.itholmes.service.UserserviceImpl"></bean>
<bean id="abc" class="com.itholmes.abc"></bean>
<aop:config>
<aop:aspect ref="abc">
<aop:pointcut id="aa" expression="execution(* com.itholmes.service.*.*(..))"/>
<!--下面的method就是上面ref引用类的方法名。-->
<aop:after method="after" pointcut-ref="aa"/>
<aop:before method="before" pointcut-ref="aa"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="aa" throwing="e"/> <!--throwing 表示异常处理的方法的参数名 (可以不再异常通知中声明异常对象)-->
<aop:after-returning method="afterReturning" pointcut-ref="aa"/>
<aop:around method="around" pointcut-ref="aa"/>
</aop:aspect>
</aop:config>
</beans>
aop注解形式:

package com.itholmes.config;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AdviceTest {
@Pointcut("execution(* com.itholmes.service.*.*(..))")
//这里的test()方法必须有,就像是一个名字一样的标识。
public void pointcut(){
}
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName() + "前置通知---");
}
//2. 正常返回
@AfterReturning("pointcut()")
public void doAfterSuccess(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName() + "正常返回通知---");
}
//3. 异常返回(与正常返回是互斥关系)
@AfterThrowing("pointcut()")
public void doAfterError(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName() + "异常通知---");
}
//4. 环绕
@Around(value = "pointcut()", argNames = "pjp")
public Object doAround(ProceedingJoinPoint pjp) {
Object[] args = pjp.getArgs();
Object result;
try {
// Before
System.out.println(pjp.getSignature().getName() + "环绕前置通知---");
result = pjp.proceed(args);
// AfterReturning
System.out.println(pjp.getSignature().getName() + "环绕返回通知---");
}catch (Throwable e){
// AfterThrowing
// System.out.println(pjp.getSignature().getName() + "环绕异常通知---");
throw new RuntimeException(e);
}finally {
// After
// System.out.println(pjp.getSignature().getName() + "环绕最终通知---");
}
return result;
}
//5. 后置通知(最终通知)
@After("pointcut()")
public void doAfter(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName() + "后置,也就是最终通知---");
}
}
不要忘记添加配置文件信息:
<bean id="annotationPointCut" class="com.itholmes.config.AdviceTest"></bean>
<aop:aspectj-autoproxy proxy-target-class="false"/>
明白正常返回 和 异常返回是互斥的。
后置(最终)通知,不管 有没有异常都会执行。
分布式锁:https://www.modb.pro/db/246339
分布式锁:https://blog.csdn.net/zhaisharap/article/details/122471322
多个用户操作同一个数据的时候,例如:快递员取货,多个快递员,去取都一件货物,这个时候就需要分布式锁解决。因为分布式它们不在一个系统中,因此就可以通过redis,zookeeper等完成分布式锁的效果。

http协议是无状态的,就是对于事务处理没有记忆能力。就是向服务器发起两次请求,服务器就不知道这两次http请求都来自同一个浏览器发出的。
cookie就是来解决http无状态的问题。
长连接,短连接,无连接:
无连接:限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
短连接:短连接是指一次请求和响应后,连接一会就关闭,这种方式可以节省资源。
长连接:从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
常见的几个请求头:
Referer=http://www.google.com
bean5种作用域:分别是:singleton、prototype、request、session、gloabal session
有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;
一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。
由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。
但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。
根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。
HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为"*")使用该方法。(简而言之,就是可以用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法)。
这是因为在跨域的情况下,在浏览器发起"复杂请求"时主动发起的。跨域共享标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。
–
HTTP1.0定义了三种请求方法:GET、POST、HEAD
HTTP1.1定义了六种请求方法:PUT、DELETE、PATCH、OPTIONS、CONNECT、TRACE
打印一下this,判断一些地址是否相同。
举个例子:我像设计一个小功能,知道当前接口已经被访问了多少次了,在controller层设计一个成员变量,通过这个成员变量达到一个计数效果。
对于多线程,上面的代码逻辑肯定会出现问题,如何解决?
AtomicInteger integer = new AtomicInteger(0);
int i = integer.getAndIncrement(); // +1 操作
int i1 = integer.decrementAndGet(); // -1 操作

乐观锁:数据库里面有一个字段version,开始业务执行前先查询version,业务执行后根据version来进行update操作(乐观锁:sql语句层次version + 1 where version = #{version}。)
sql语句的修改丢失,也可以用悲观锁(select … for update)处理。
对于这种业务有增有减,就容易产生ABA问题。ABA问题:由A变成B,再由B编程了A。这种ABA问题。
transient关键字标记的成员变量不参与序列化过程,transient关键字只能修饰变量,而不能修饰方法和类。

见:https://www.jb51.net/article/216853.htm
代码里面 / 都是指的如下地方:

将页面放到web-inf下面,就可以通过走servlet来安全访问。

springmvc容器 与 spring容器是子父容器。 开始先扫描springmvc容器,因此一般springmvc.xml文件里面,最好不要扫描service的路径。
当然,Spring.xml文件就要扫描service层下的实现类,进而放到spring容器里面,是为了配置mybatis的增强事务。
上面不是绝对,如果把事务整合什么的也都放到springmvc,也是可以行得通的。
见:https://blog.csdn.net/IT_Holmes/article/details/123089091?spm=1001.2014.3001.5502
单例模式:
package com.itholmes.config;
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){
}
//饿汉式
public static Singleton getSingleton(){
return singleton;
}
}
package com.itholmes.config;
public class Singleton {
private static Singleton singleton = null;
private Singleton(){
}
//懒汉式
public static Singleton getSingleton(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
见:https://www.runoob.com/design-pattern/factory-pattern.html
1、assert condition;
这里condition是一个必须为真(true)的表达式。如果表达式的结果为true,那么断言为真,并且无任何行动
如果表达式为false,则断言失败,则会抛出一个AssertionError对象。这个AssertionError继承于Error对象,
而Error继承于Throwable,Error是和Exception并列的一个错误对象,通常用于表达系统级运行错误。
2、asser condition:expr;
这里condition是和上面一样的,这个冒号后跟的是一个表达式,通常用于断言失败后的提示信息,说白了,它是一个传到AssertionError构造函数的值,如果断言失败,该值被转化为它对应的字符串,并显示出来。
public class Test {
public static void main(String[] args) {
System.out.println("start");
assert true;
System.out.println("go on");
assert false:"stop";
System.out.println("end");
}
}
需要观察断言的运行情况,就需要打开系统类的assertion功能 ,我们可使用-esa参数打开,使用 -dsa参数关闭。 -esa和-dsa的全名为-enablesystemassertions和 -disenablesystemassertions,全名和缩写名有同样的功能。

Spring的Assert断言工具类,通常用于数据合法性检查。位于 org.springframework.util.Assert包下,使用Assert可以使复杂的判断变得更加简单。

