It is also possible to provide all beans of a particular type from the ApplicationContext by adding the annotation to a field or method that expects an array of that type:
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
}
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用上述注解对分层中的类进行注释。@Service用于标注业务层组件.@Controller用于标注控制层组件(如struts中的action).@Repository用于标注数据访问组件,即DAO组件. @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
An attribute is a server variable that exists within a specified scope i.e.:
application: available for the life of the entire application
session: available for the life of the session
request: only available for the life of the request
page (JSP only): available for the current JSP page only
@Aspect
// 注意需要依赖注入
@Component
public class EmployeeAspect {
// 注意方法()内有两个点, 代表任意参数
@Pointcut("execution(* com.journaldev.spring.service.*.get*(..))")
public void pointCut(){
System.out.println("enter pointcut");
}
@Before("pointCut()")
public void before(){
}
}
* 切面进入的条件
public , non static , non final ,called by class outside(非必须)
若要在类的内部调用中执行切面, 例如类里面有两个方法A, B, 在A调用B的时候进入切面, 则需要如下写法:
// 注意该类需要由spring管理,并生成, 若是在外部 Test t = new Test(); t.methodA();或者 t.methodB(); 均不能进入切面
@Component
public class Test{
@Resource Test test
public void methodA(){
// something
test.methodB();
// something
}
public void methodB(){}
}
Transaction 1 Transaction 2
/ Query 1 /
SELECT age FROM users WHERE id = 1;
/ will read 20 /
/ Query 2 /
UPDATE users SET age = 21 WHERE id = 1;
/ No commit here /
/ Query 1 /
SELECT age FROM users WHERE id = 1;
/ will read 21 /
ROLLBACK; / lock-based DIRTY READ /
* 不可重复读(unrepeatable read)
因为select可能不需要锁, 或者发生在两次select锁获取之前, 就会读到不可重复读取的数据, 根据不同的隔离级别, 会有不同的数据.
> At the SERIALIZABLE and REPEATABLE READ isolation levels, the DBMS must return the old value for the second SELECT. At READ COMMITTED and READ UNCOMMITTED, the DBMS may return the updated value; this is a non-repeatable read.
* 有两种策略来处理此种情况
1. 延迟事务2的执行直到事务1提交或者回滚, 等于说维护一个时序: serial schedule T1, T2.
2. 为了获取更好的性能,让事务2被先提交, 事务1的执行必须满足时序 T1, T2, 若不满足事务1被回滚.
在不同模型下, 结果会不一样
> Using a lock-based concurrency control method, at the REPEATABLE READ isolation mode, the row with ID = 1 would be locked, thus blocking Query 2 until the first transaction was committed or rolled back. In READ COMMITTED mode, the second time Query 1 was executed, the age would have changed.
> Under multiversion concurrency control, at the SERIALIZABLE isolation level, both SELECT queries see a snapshot of the database taken at the start of Transaction 1. Therefore, they return the same data. However, if Transaction 1 then attempted to UPDATE that row as well, a serialization failure would occur and Transaction 1 would be forced to roll back.
> At the READ COMMITTED isolation level, each query sees a snapshot of the database taken at the start of each query. Therefore, they each see different data for the updated row. No serialization failure is possible in this mode (because no promise of serializability is made), and Transaction 1 will not have to be retried.(这段怎么跟之前说的 read commited 不一样 ? )
* 幻象读(Phantom reads),是不可重复读的特例, 相当于是范围读.
Transaction 1 Transaction 2
/ Query 1 /
SELECT FROM users
WHERE age BETWEEN 10 AND 30;
/ Query 2 /
INSERT INTO users(id,name,age) VALUES ( 3, 'Bob', 27 );
COMMIT;
/ Query 1 /
SELECT FROM users
WHERE age BETWEEN 10 AND 30;
COMMIT;
> Note that Transaction 1 executed the same query twice. If the highest level of isolation were maintained, the same set of rows should be returned both times, and indeed that is what is mandated to occur in a database operating at the SQL SERIALIZABLE isolation level. However, at the lesser isolation levels, a different set of rows may be returned the second time.
> In the SERIALIZABLE isolation mode, Query 1 would result in all records with age in the range 10 to 30 being locked, thus Query 2 would block until the first transaction was committed. In REPEATABLE READ mode, the range would not be locked, allowing the record to be inserted and the second execution of Query 1 to include the new row in its results.
* 以上均参见[wiki isolation](https://en.wikipedia.org/wiki/Isolation_(database_systems)#Dirty_reads)
Transaction 1 Transaction 2
/ Query 1 /
SELECT FROM users WHERE id = 1;
/ Query 2 /
UPDATE users SET age = 21 WHERE id = 1;
COMMIT;
/ in multiversion concurrency
control, or lock-based READ COMMITTED /
/ Query 1 /
SELECT FROM users WHERE id = 1;
COMMIT;
/ lock-based REPEATABLE READ /
Isolation level Dirty reads Non-repeatable reads Phantoms
Read Uncommitted may occur may occur(1) may occur(2)
Read Committed don't occur may occur(1) may occur(2)
Repeatable Read don't occur don't occur may occur(2)
Serializable don't occur don't occur don't occur
spring的理解
spring是以IOC和AOP为核心的众多组件的总称, 其他还包括spring-boot, spring-mvc等组件, 涵盖了后台开发的从前端到后台交互, 后台分层, 中间件, 数据库等持久层等几乎方位的支持.
spring IOC
大致思想 首先spring的控制反转来源于依赖倒置(Dependency Inversion Principle )的思想, 传统的依赖顺序是高层依赖底层, 而依赖倒置指的是底层依赖高层. 例如车子的建造, 车子依赖车身, 车身依赖底盘, 底盘依赖车轮, 若需要改动车轮的规格, 则以上所有东西都需要改, 若反过来, 先定好车子的样子, 车身 -> 车子, 底盘 -> 车身, 轮子 -> 底盘, 要改车轮, 不会影响其他.
概念关系 依赖倒置是思想, 控制反转是实现该思想的一个思路, 依赖注入是该思路的具体实现方法, 依赖注入可以简要说是把底层类作为参数传递给上层类, 实现上层对下层的控制, 而IOC容器则封装了底层类的构造方法, 不需要知道底层类的实现细节以及 具体的构造函数的如何调用, 只需要按照依赖注入即可.
以下内容均参考 spring-framework-reference/core/beans-annotation-config
xml和annotation两种方式比较
annotation使配置更简洁, 和源码放在一起, 更精确, 但是配置比较分散, 不在一个地方很难控制 ; xml的方式不需要去动源码, 所以不需要重新编译,
@Required 和@Autowired 比较
前者如果没有注入成功, 会报错, 且只能用于setter method.; 后者可以设置是否required(默认true) ,并且当无法autowire时会自动忽略, 适用于constructor, field , setter method or config method.
@Autowired
按照byType注入, 可以设置required=false, 找不到bean时也不报错, 后续可能报NPE.
用于constructor, 当构造函数有多个时, 可以将指定一个进行autowired, 否则将默认以贪婪模式(参数最多的构造函数进行构造).
获取所有类型的bean
@Qualifier
可以结合@Autowire使用, 当某个type有多个实例时, 可以用@Qualifier 指定某个id的bean注入. @Qualifier和@Autowired结合使用时, 和@Resource几乎等同.
@Resource
既可以byName, 也可以byType注入, 默认byName, 就是按照bean的id注入.
如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
问题 在细看一下@Qualifier
@Component、@Repository、@Service、@Controller
如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用上述注解对分层中的类进行注释。@Service用于标注业务层组件.@Controller用于标注控制层组件(如struts中的action).@Repository用于标注数据访问组件,即DAO组件. @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Bean与@Component的区别
前者是显式的返回一个object, 然后注入到application context, 让spring代管理, 例如可以适用于第三方的lib, 无法再源码上@Component; 后者是让spring创建并管理, 隐式的创建.
classpath*: / 与 classpath:/
build project
web项目下相对路径和绝对路径:
前后台传输数据
mybatis返回map
mapper:
jetty启动时修改资源文件,可以通过update更新
修改/${jetty_home}/etc/webdefault.xml 将true改为false 并在pom文件中配置
httpServletResquest
getAttribute()
getParameter()
spring @value
static field cant inject directly.
{configProperties.configVal} , ${configVal} 区别
link
其他用法 link
mybatis
Boolean 值传递
数据库类型是tinyInt, dto字段类型是Boolean或boolean,
spring AOP
pointcut 切点
指定在哪些类和哪些方法做切入
advice 增强
定义加强类的逻辑, 方法前还是方法后等
advisor 切面, 将pointcut和advice结合起来
JDK动态代理 只能对接口或者实现类进行方法切面, 问题 为什么只能基于接口做代理.
CGLib代理
采用动态创建子类的方法, 因此不能对final, private等方法进行切面; 而且相比于JDK性能比较高, 创建代理对象的时间比较长, 适用于spring 多数类都是单例的情况.
示例代码
// spring application.xml config
// 下面这种方式用于CGLIB, 可以切面类的非接口方法, 否则上面那种基于JDK的代理只能切接口方法
@Aspect // 注意需要依赖注入 @Component public class EmployeeAspect {
}
Transaction 1 Transaction 2 / Query 1 / SELECT age FROM users WHERE id = 1; / will read 20 / / Query 2 / UPDATE users SET age = 21 WHERE id = 1; / No commit here / / Query 1 / SELECT age FROM users WHERE id = 1; / will read 21 / ROLLBACK; / lock-based DIRTY READ /
/ Query 1 / SELECT FROM users WHERE age BETWEEN 10 AND 30; / Query 2 / INSERT INTO users(id,name,age) VALUES ( 3, 'Bob', 27 ); COMMIT; / Query 1 / SELECT FROM users WHERE age BETWEEN 10 AND 30; COMMIT;
Transaction 1 Transaction 2 / Query 1 / SELECT FROM users WHERE id = 1; / Query 2 / UPDATE users SET age = 21 WHERE id = 1; COMMIT; / in multiversion concurrency control, or lock-based READ COMMITTED / / Query 1 / SELECT FROM users WHERE id = 1; COMMIT; / lock-based REPEATABLE READ /
Isolation level Dirty reads Non-repeatable reads Phantoms Read Uncommitted may occur may occur(1) may occur(2) Read Committed don't occur may occur(1) may occur(2) Repeatable Read don't occur don't occur may occur(2) Serializable don't occur don't occur don't occur
(1): 返回修改后的值 (2): 会返回新插入的值 Serializable : 均会阻塞事务2的更新, 直到事务1提交