总结

javaEE

spring:方便解耦,简化开发

1. spring 对象关系映射ORM

ORM:对象关系映射 它通过现实ORM规范,完成面向对象的编程语言到关系数据库的映射。它可以把关系型数据库封装成对象,解决面向对象编程语言与底层关系数据库不协调的问题。它是面向对象编程言语与关系数据库之间的桥梁。

ORM映射基本规则

1
2
3
4
5
6
7
1. 类与表相对应 
2. 类的属性(成员变量)与表的字段相对应
3. 类的实例与表中具体的一条记录相对应
4. 一个类可以对应多个表,一个表也可以对应多个类
5. 数据库中的表可以没有主键,但是类的实例中必须设置主键字段
6. 数据库中表与表之间的关系(如外键)映射成为对象之间的关系
7. 对象中属性(成员变量)的个数和名称可以和表中定义的字段个数和名称不一样

2.Spring Bean 实例化方式

  1. 调用构造器创建Bean
1
2
3
第一种方式:使用默认无参构造函数
<!--在默认情况下:它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。-->
<bean id="accountService" class="com.han.service.impl.AccountServiceImpl"/>
  1. 调用静态工厂方法创建Bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
public static IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
id 属性:指定 bean 的 id,用于从容器中获取
class 属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法-->
<bean id="accountService" class="com.han.factory.StaticFactory" factory-method="createAccountService"></bean>
  1. 调用实例工厂方法创建Bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
public IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
先把工厂的创建交给 spring 来管理。然后在使用工厂的 bean 来调用里面的方法
factory-bean 属性:用于指定实例工厂 bean 的 id。
factory-method 属性:用于指定实例工厂中创建对象的方法。-->
<bean id="instancFactory" class="com.han.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instancFactory" factory-method="createAccountService"></bean>

Bean对象的作用范围

1
2
3
4
5
6
* singleton :默认值,单例的.
* prototype :多例的.
* request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
* session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
* global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么
globalSession 相当于 session.

Bean生命周期

1
2
3
4
5
6
7
8
9
10
11
12
单例对象:scope="singleton"
一个应用只有一个对象的实例。它的作用范围就是整个引用。
生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
多例对象:scope="prototype"
每次访问对象时,都会重新创建对象实例。
生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。

控制反转(IOC)与依赖注入(DI)

控制反转(Inversion of Control),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入,还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

IOC和DI的区别

1
2
3
(1) IOC:控制反转,把对象创建交给spring来管理
(2) DI:依赖注入,向类里面的属性设置值
(3) 关系:依赖注入不能单独存在,需要在IOC基础之上完成操作

IOC的作用:削减程序之间的耦合(解除代码中的依赖关系)

构造器注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--使用构造函数的方式,给 service 中的属性传值
<constructor-arg/>标签属性
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称
=======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean-->
<bean id="accountService" class="com.han.service.impl.AccountServiceImpl">
<constructor-arg name="name" value=" 张三 "></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>

set方法注入

1
2
3
4
5
6
7
8
9
10
11
<!-- 通过配置文件给 bean 中的属性传值:使用 set 方法的方式
property属性:
name:找的是类中 set 方法后面的部分
ref:给属性赋值是其他 bean 类型的
value:给属性赋值是基本数据类型和 string 类型的-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>

Spring 中的 AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
**Joinpoint**( 连接点):(业务接口中,所有的方法都叫做连接点)
所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。
**Pointcut**( 切入点):(业务接口中,被增强的方法)
所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。
**Advice**( 通知/ 增强):
所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。
**Introduction**( 引介):
引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。
**Target**( 目标对象):
代理的目标对象。
**Weaving**( 织入):
是指把增强应用到目标对象来创建新的代理对象的过程。
spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
**Proxy** (代理):
一个类被 AOP 织入增强后,就产生一个结果代理类。
**Aspect**( 切面):
是切入点和通知(引介)的结合。

AOP的作用

1
2
3
4
作用:在程序运行期间,不修改源码的情况下对已有的方法进行增强。
优势:减少重复代码
提高开发效率
维护方便

动态代理

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
* 动态代理:
* 特点:字节码随用随创建,随用随加载
* 作用:不修改源码的基础上对方法增强
* 分类:
* 基于接口的动态代理
* 基于子类的动态代理
* 基于接口的动态代理:
* 涉及的类:Proxy
* 提供者:JDK官方
* 如何创建代理对象:
* 使用Proxy类中的newProxyInstance方法
* 创建代理对象的要求:
* 被代理类最少实现一个接口,如果没有则不能使用
* newProxyInstance方法的参数:
* ClassLoader:类加载器
* 它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。固定写法。
* Class[]:字节码数组
* 它是用于让代理对象和被代理对象有相同方法。固定写法。
* InvocationHandler:用于提供增强的代码
* 它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
* 此接口的实现类都是谁用谁写。
*/
IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),
producer.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 作用:执行被代理对象的任何接口方法都会经过该方法
* 方法参数的含义
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前执行方法所需的参数
* @return 和被代理对象方法有相同的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//提供增强的代码
Object returnValue = null;

//1.获取方法执行的参数
Float money = (Float)args[0];
//2.判断当前方法是不是销售
if("saleProduct".equals(method.getName())) {
returnValue = method.invoke(producer, money*0.8f);
}
return returnValue;
}
});
proxyProducer.saleProduct(10000f);
}

FM8EgP.png

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
31
32
33
34
35
36
37
38
39
40
41
42
43
<!-- spring中基于XML的声明式事务控制配置步骤
1、配置事务管理器
2、配置事务的通知
此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的
使用tx:advice标签配置事务通知
属性:
id:给事务通知起一个唯一标识
transaction-manager:给事务通知提供一个事务管理器引用
3、配置AOP中的通用切入点表达式
4、建立事务通知和切入点表达式的对应关系
5、配置事务的属性
是在事务的通知tx:advice标签的内部
-->

<!-- xml 配置事务 -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 配置事务的属性
isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
</tx:attributes>
</tx:advice>

<!-- 配置aop-->
<aop:config>
<!-- 配置切入点表达式-->
<aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>
<!--建立切入点表达式和事务通知的对应关系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
1
2
3
4
5
6
7
<!--注解式事务控制-->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启spring对注解事务的支持-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

spring中常用的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component 把资源让spring来管理。相当于xml中的bean
@Controller 用于表现层的注解
@Service 用于业务层的注解
@Repository 用于持久层的注解
@Autowired 自动按照类型注入
@Qualifier 按照Bean的id注入 需要结合@Autowired一起使用
@Resource 直接按照bean的id注入
@Value 注入基本数据类型和String数据类型
@Scope 指定的bean的作用范围

@Configuration 指定当前类是一个spring的配置类
@ComponentScan 用于指定spring容器初始化要扫描的包
@Bean 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring的容器

@Transactional 事务

3.solr创建索引库的方式

4.异常处理

参考全局异常

5.Dubbox

dobbox消息传递使用的是zookeeper

dubbox优点:降低耦合度,可以搭集群,增加访问数量
dubbox缺点:传递存在风险

6.MyBatis的延迟加载与缓存

开启 Mybatis 的延迟加载策略

在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延迟加载的配置。

1
2
3
4
5
6
7
<!-- 开启延迟加载的支持 -->
<settings>
<!--开启mybatis全局支持延迟加载, 可以使用fetchType属性来控制对应的方法是否延迟加载,覆盖该方法的加载方式-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--将积极加载设置为延迟加载 mybatis3.4.1后默认就是延迟加载,不设置也是可以的-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>

mybatis开启懒加载,只要设置 lazyLoadingEnable属性为true来开启全局延迟加载,fetchType属性可以控制某个指定的方法实现立即加载或延迟加载。

mybatis的一级缓存

mybatis默认是存在一级缓存的,一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。

清空缓存的方式

1
2
3
1. SqlSession 的修改,添加,删除,commit(),close()等方法时
2. 调用sqlSession.clearCache()
3. 设置statement配置中的flushCache='true' 属性

Mybatis的二级缓存

二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式来保存对象。

二级缓存的开启与关闭

第一步:在 SqlMapConfig.xml 文件开启二级缓存

1
2
3
4
5
<settings>
<!-- 开启二级缓存的支持 -->
<setting name="cacheEnabled" value="true"/>
</settings>
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。

第二步:配置相关的 Mapper 映射文件

1
2
3
4
<mapper namespace="com.han.dao.user">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>

第三步:配置 statement 上面的 useCache 属性

1
2
3
4
5
6
7
<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>
将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个 statement 要使用
二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。

7.springMVC执行流程

FZHXQ0.jpg

客户端发送request请求,请求被发送到前端控制器DispatcherServlet,前端控制器请求查找Handler,找到处理器映射器HandlerMapping,handlerMapping根据请求的url找到对应的controller和方法方法,并返回给前端控制器,前端控制器会请求处理器适配器执行controller中的方法,返回modelAndView给前端控制器,前端控制器请求视图解析器解析,跳转到视图,对视图进行渲染并将处理的结果返回给用户。

springMVC的设计模式:适配器模式(处理器适配器)

8.HashMap

FePsP0.png

1
2
3
hashMap的默认长度为2^4 = 16
map的最大允许长度为2^30 , integer的最大长度为2^31-1
当map存储到12条数据时,map会自动扩容,增长的长度为原来长度的2的幂次方

hashMap的put方法

初始化table
FeinJ0.png

FeiTTs.png

FeiImQ.png

hash算法是根据大量的数据演练得出的,利用了泊松分布,使得key均匀的分布在每个链表上,这样查询速度快

FeFHDe.png

h & (length-1)是保证了数组下标永远小于16,避免了数组越界问题

FekUKO.png

FekTGq.png

添加entry

Fekcxf.png

扩容

FekyGt.png

添加数据

FekRsS.png

HashMap的get方法

FmA93t.png

FmkvAH.png

线程

1
2
3
4
5
6
7
8
9
10
11
12
如何判断线程是否安全
是否 存在多线程环境
在多线程环境下,是否有共享的变量
在多线程环境下是否多共享变量进行写操作
三个条件同时满足,才会出现线程安全的问题

如何解决?
只要破坏上面的三个条件之一即可
对于2,不建议在成员的位置上定义变量
对于3,加锁(同步代码块)

生产者消费者问题 -->等待唤醒机制
0%