一.Spring概念
1.是一个开源的轻量级框架
2.spring核心主要两部分
(1)aop:面向切面编程,扩展功能不是修改代码实现
(2)ioc:控制反转:把对象的创建不通过new的方式,而是交给spring配置创建对象
3.spring是一站式框架
在javaee的三层结构中,每一层都提供不同的解决办法
web层:springMVC
service:spring的ioc
dao层:spring的jdbcTemplate
4.ioc
1)把对象的创建交给spring管理
2)ioc操作两部分
A.ioc的配置文件方式
B.ioc的注解方式
3)底层原理(搞内聚低耦合)
A.底层使用技术
a.xml配置文件
b.dom4j解决XML
c.工厂设计模式
d.反射
4)配置文件步骤
A:spring核心配置文件名称和位置不是固定的,建议放到src下面,官方建议名称为applicationContext.xml
B:引入schema约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--此处配置实体类-->
</beans>
C:配置对象
<!--无参构造配置-->
<bean id="user" class="cn.zsl.bean.User"></bean>
5.Bean管理——配置文件方式
(1)Bean实例化方式三种
A:使用类的无参构造创建(重点)
B:使用静态工厂创建:创建静态方法返回对象
C:使用实例工厂创建:不是静态方法,而是创建类的对象来返回
(2)Bean标签常用属性
id:起名称,id属性值名称任意命名,不能包含特殊符号。根据id得到配置对象
class:创建对象所在类的全路径
name:功能和id属性一样,id属性不能包含特殊符号,但是再那么属性值里面可以包含特殊符号,基本不用了。
scope:包含以下值
singleton:默认值,单例,只有一个对象
prototype:多例
request:创建对象把对象放到request里面
session:创建对象把对象放到session里面
globalSession:创建对象把对象放到globalSession里面
(3)属性注入:创建对象的时候向类里面的属性设置值
A:Java中的属性注入方式 三种
a.使用有参构造方法注入
b.使用set方法注入
c.使用接口注入
B:配置文件注入类中属性值,只支持上面a、b两种方法
a.使用有参构造方法注入,使用constructor-arg标签 ,name属性表示成员变量名,value表示要传入的值
<bean id="user" class="cn.zsl.bean.User">
<constructor-arg name="name" value="张三"></constructor-arg>
</bean>
b.使用set方法注入,使用property标签,name属性表示成员变量名,value表示要传入的值
<bean id="user" class="cn.zsl.bean.User">
<property name="name" value="张三"></property>
</bean>
C:注入对象类型属性(重点)
若A类中含有B类的对象,用ioc来实现的方法
a.在A中把B作为类型属性
b.生成B类型的set方法
c.在配置文件中注入对象属性,在A中添加属性标签property,name属性表示成员变量名,ref表示类B类配置bean标签中的id值
<bean id="b" class="cn.zsl.bean.B"></bean>
<bean id="a" class="cn.zsl.bean.A">
<property name="name" ref="b"></property>
</bean>
D:注入复杂数据
a.数组类型:使用property标签下的list标签下的value标签对数组赋值
b.List集合:使用property标签下的list标签下的value标签对List集合赋值
c.map集合:使用property标签下的map标签下的entry标签对map集合赋值,key是键value是值
d.properties:使用property标签下的props标签下的prop标签对properties赋值,key是实体中的键
<bean id="user" class="cn.zsl.bean.User">
<!-- 对数组属性赋值 -->
<property name="array">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<!-- 对List属性赋值 -->
<property name="list">
<list>
<value>手机</value>
<value>电脑</value>
<value>平板</value>
</list>
</property>
<!-- 对map属性赋值 -->
<property name="map">
<map>
<entry key="aa" value="tom"></entry>
<entry key="bb" value="jerry"></entry>
<entry key="cc" value="friends"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="username">root</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
E:IOC和DI区别
IOC:控制反转,把对象的创建交给spring管理
DI:依赖注入,向类中的属性进行注入值
关系:依赖注入不能单独存在,需要在IOC基础上完成操作。
6.Spring整合Web项目原理
(1)加载spring核心配置文件
new对象,功能可以实现,效率很低
(2)实现思想:要把加载配置文件和创建对象过程在服务器启动时完成
(3)实现原理:
A:ServletContext对象
B:监听器
(4)具体流程
A.在服务器启动时,系统为每个项目创建一个ServletContext对象
B.在ServletContext对象创建的时候使用监听器可以监听到ServletContext对象在什么时候创建
C.监听到ServletContext创建时,项目加载spring配置文件,把配置文件中的配置对象进行创建
D.把创建出来的对象放在ServletContext域对象里面(setAttribute()方法)
E.获取对象时,到ServletContext域得到对象(getAttribute()方法)
7.Bean管理——注解方式
(1)注解:代码里面的特殊标记,使用注解可以完成功能
注解写法:@注解名称(属性名称=属性值)
注解可以使用在类、方法和属性上面
(2)步骤:
A.导入jar包,包括基本spring包还有一个注解包
B.创建类,属性和方法
C.创建配置文件,引入约束,开启注解扫描
<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" 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">
<!-- 开启注解扫描
到包中扫描类、方法、属性上是否有注解
如果向扫描多个类中的注解,可以让base-package="cn.zsl" ,如果是不同包下的类,甚至可以让base-package="cn"
-->
<context:component-scan base-package="cn.zsl.bean"></context:component-scan>
<!-- 只会扫描属性上面的注解 -->
<context:annotation-config></context:annotation-config>
</beans>
D.注解创建对象 4个注解
@Component(vlaue=”user”) //和< bean id=”user” class=”“>效果一样,user表示对象名
@Controller:web层
@Service :业务层
@Repository :持久层
4个效果是一样的,用法也一样。
E:创建单实例对象
@scope(value=”singleton”) //singleton默认值,单实例 、prototype多实例 其他用法见配置文件方式
(3)属性注入
A.@Autowired自动注入
B.@Resourse(name=”user”) :name表示赋值,如果注入对象类型,则和注解创建对象的value值要相同或者配置文件方式创建对象的id相同
注:使用注解方式,A类中不需要设置B类对象属性的set方法,标签自动注入
(4)注入对象类型属性
若A类中含有B类的对象,用注解方式来实现
A:创建A类和B类
B:注解方式创建A、B类的对象
C:在A类中定义B类型属性,用注解标签注入该对象属性
7.配置文件和注解混合方式
创建对象都是使用配置文件方式,注入属性都是用注解方式
二.AOP
1.AOP:面向切面编程,采取横向抽取机制,取代了传统的纵向继承体系重复性代码。
2.AOP原理:
3.AOP操作术语:
4.aspectj: 在spring里面进行aop操作,使用aspectj实现
(1)aspectj不是spring一部分,和spring一起使用进行aop操作
(2)Spring2.0以后新增了对AspectJ支持
(3)使用aspectj实现aop有两种方式
A.基于aspectj的xml配置
B.基于aspectj的注解方式
5.aspectj的使用准备
(1)配置文件引入约束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->
</beans>
(2)使用表达式配置切入点
A.切入点:实际增强的方法
B.常用的表达式 execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
a. execution(* cn.itcast.aop.Book.add(..)) :表示cn.itcast.aop包下Book类的add()方法
b. execution(* cn.itcast.aop.Book.*(..)):表示cn.itcast.aop包下Book类的所有方法
c. execution(* * .*(..)) :表示所有方法
d. 匹配所有save开头的方法 execution(* save*(..)):表示所有以save开头的方法
6.配置文件方式使用aspectj的aop操作
(1)添加增强类和方法
如果是要添加around环绕增强方法,需要对该方法添加一个ProceedingJoinPoint类型的形参,通过该形参的proceed()方法来调用被增强的方法,该proceedingJoinPoint.proceed()就表示被增强的方法
public void aroundAdd(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//方法之前
System.out.println("环绕之前");
//调用被增强方法
proceedingJoinPoint.proceed() ;
//方法之后
System.out.println("环绕之后");
}
(2)配置对象,在配置文件中对要使用的类进行添加配置对象
<!-- 对Book类的add()方法添加一个MyBook类中的增强方法 -->
<!-- 1 配置对象 -->
<bean id="book" class="cn.zsl.bean.Book"></bean>
<bean id="myBook" class="cn.zsl.bean.MyBook"></bean>
<!-- 2 配置aop操作 -->
<aop:config>
<!-- 2.1配置切入点 -->
<aop:pointcut expression="execution(* cn.zsl.bean.Book.*(..))" id="pointcut1"/>
<!-- 2.2配置切面:把增强用到方法上面 -->
<aop:aspect ref="myBook">
<!-- 配置增强类型
aop:before:前置增强
aop:after:后置增强
aop:around:环绕增强
...
method:增强类里面使用哪个方法作为增强方法
pointcut-ref:要增强的切入点(方法),要和上面定义的相同
-->
<aop:before method="beforeAdd" pointcut-ref="pointcut1"/>
<aop:after method="afterAdd" pointcut-ref="pointcut1"/>
<aop:around method="aroundAdd" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
7.log4j : 使用log4j查看日志
使用方法:
(1)导入log4j的jar包
(2)复制log4j的配置文件,复制到src下面
设置日志级别
(1)info:看到基本信息
(2)debug:看到更详细信息
8.Spring整合Web项目
每次访问action时候,都会加载spring配置文件
(1) 解决方案:
A.在服务器启动时候,创建对象加载配置文件
B.底层使用监听器、ServletContext对象
(2)在spring里面不需要我们自己写代码实现,会帮我们封装
A.封装了一个监听器,只需要 配置监听器 就可以了
B.配置监听器之前做事情:导入spring整合web项目jar包(spring-web-4.2.4.RELEASE.jar)
C.指定加载spring配置文件位置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:bean1.xml</param-value>
</context-param>
9.注解方式使用aspectj的aop操作
(1)创建增强类和方法
(2)配置类和增强类对象
(3)配置文件开启aop操作
<!-- 开启aop操作 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
(4)在增强类上面使用注解完成aop操作
A.在类上添加@Aspect标签
B.在方法上添加@Before、@After、@Around等标签,子标签value值为 常用的表达式 execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>),如下:
@Before(value=”execution(* cn.zsl.bean.Book.*(..))”)
10.Spring的jdbcTemplate操作
(1)spring框架一站式框架
针对javaee三层,每一层都有解决技术
在dao层,使用 jdbcTemplate
(2)spring对不同的持久化层技术都进行封装
dbcTemplate使用和dbutils使用很相似,都数据库进行crud操作
(3)使用方法
A.导入jar包
B.创建对象,设置数据库信息
C.创建jdbcTemplate对象,设置数据源
D.调用jdbcTemplate对象里面的方法实现操作
增删改都是调用update()方法实现
//配置数据库信息
DriverManagerDataSource dataSource = new DriverManagerDataSource() ;
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///springjdbcTemplatetest");
dataSource.setUsername("root");
dataSource.setPassword("root");
//创建jdbcTemplate对象,设置数据源
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource) ;
//调用jdbcTemplate对象里面的update方法实现操作
String sql = "insert into user value(?,?)" ;
int rows = jdbcTemplate.update(sql,"zhangsan","26") ;
System.out.println(rows);
(4)查询数据操作
配置数据库和创建jdbcTemplate对象步骤一样,调用方法不同
A.查找返回一个值
// 查找返回一个值,queryForObject()方法,第一个参数表示sql语句,第二个参数表示返回值的类型的class文件
String sql = "select count(*) from user";
int count = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println(count);
B.查找返回一个对象,这时需要自己创建一个RowMapper接口的对象,用于封装查找到的数据
// 查找返回对象,调用queryForObject(),第一个参数表示sql语句,第二个参数表示RowMapper接口对象,表示获取到一行数据的User对象,第三个参数是可变参数
String sql = "select * from user where username = ?";
User user = jdbcTemplate.queryForObject(sql, new MyRowMapper() , "zhangsan");
System.out.println(user);
class myRowMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet rs, int num) throws SQLException {
//1从结果集里把数据得到
String username = rs.getString("username") ;
String password = rs.getString("password") ;
//2把得到的数据封装到对象里面
User user = new User() ;
user.setUsername(username);
user.setPassword(password);
return user ;
}
}
C.查询返回list集合
// 查找返回对象,调用query()方法,第一个参数表示sql语句,第二个参数表示RowMapper接口对象
String sql = "select * from user";
List<User> list= jdbcTemplate.query(sql, new MyRowMapper()) ;
System.out.println(list);
11.配置c3p0连接池和dao使用jdbcTemplate
(1)配置c3p0连接池
(2)dao使用jdbcTemplate
1)创建service和dao,配置service和dao对象,在service注入dao对象
2)创建jdbcTemplate对象,把模板对象注入到dao里面
3)在jdbcTemplate对象里面注入dataSource
12.事务管理
(1)事物:对数据库操作的最基本单元
(2)事物特性:原子性、一致性、隔离性、持久性
(3)不考虑隔离会产生的问题:
脏读:一个事务读到另一个事务未提交的更新数据。
不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。
幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。
丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。
(4)解决方案:设置隔离级别
(5)Spring事务管理api