Spring是一个分层的JavaSE/EEfull-stack(一站式)轻量级开源框架。
一站式框架:有EE开发的每一层解决方案,WEB层:springmvc,Service层:Spring的Bean管理,Spring声明式事务,DAO层:Spring的jdbc模板,Spring的ORM模块。
核心容器:Beans、Core、Context、SpEL
Spring的IOC的底层实现:
好的程序设计满足OCP原则,在尽量不修改程序源码的基础上对程序进行扩展。
工厂+反射+配置文件 实现程序解耦合
*<bean id="userDAO" class="xxx.UserDAOImpl"></bean>
class BeanFactory{
public static Object getBean(String id){
//解析XML
//反射
Class clazz = Class.forName();
return clazz.newInstance();
}
}
IOC和DI
IOC:控制反转,将对象的创建权反转给了Spring
DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来。
Spring的工厂类
BeanFactory :是在getBean的时候才会生成类的实例
ApplicationContext:在加载applicationContext.xml时候就会创建,就会将Spring管理的类都实例化
ClassPathXmlApplicationContext:加载类路径下的配置文件
@Test
public void demo2(){
//创建spring的工厂
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userDAO = (UserDAO) applicationContext.getBean("userDAO");
userDAO.save();
}
Spring的配置
XML的提示配置:Schema的配置
Bean的相关的配置:<bean>标签的id和name的配置
Bean的生命周期的配置
init-method :Bean被初始化的时候执行的方法
destroy-method:Bean被销毁的时候执行的方法(Bean是单例创建,工厂关闭)
Bean的作用范围的配置
scope:Bean的作用范围
singleton:默认的,Spring会采用单例模式创建这个对象
prototype:多例模式
request:应用在web项目中,Spring创建这个类以后,将这个类存入到request范围中
session:应用在web项目中,Spring创建这个类以后,将这个类存入到session范围中
globalsession:应用在web项目中,必须在porlet环境下使用
Spring的属性注入:
构造方法的方式的属性注入:
<!-- 构造方法的方式 -->
<bean id="car" class="com.itheima.spring.demo4.Car">
<constructor-arg name="name" value="宝马"/>
<constructor-arg name="price" value="800000"/>
</bean>
Set方法的方式的属性注入:
Set方法的属性注入:
<!-- set方法的方式 -->
<bean id="car2" class="com.itheima.spring.demo4.Car2">
<property name="name" value="奔跑"/>
<property name="price" value="10000000"/>
</bean>
Set方法设置对象类型的属性
<!-- set方法注入对象类型的属性 -->
<bean id="employee" class="com.itheima.spring.demo4.Employee">
<!-- value:设置普通类型的值,ref:设置其他的类的id或name -->
<property name="name" value="涛哥"/>
<property name="car2" ref="car2"/>
</bean>
P名称空间的属性注入
通过引入p名称空间完成属性的注入:
写法:
普通属性 p:属性名=“值”
对象属性 p:属性名-ref=“值”
P名称空间的引入:
xmls:p="http://www.springframework.org/schema/p"
使用p名称空间:
<bean id="car2" class="com.itheima.spring.demo4.Car2" p:name="QQ" p:price="30000"></bean>
<bean id="employee" class="com.itheima.spring.demo4.Employee" p:name="王东" p:car2-ref="car2"></bean>
SpEL的属性注入:
语法:#{SpEL}
<!-- SpEL的属性注入 -->
<bean id="carInfo" class="com.itheima.spring.demo4.CarInfo"></bean>
<bean id="car2" class="com.itheima.spring.demo4.Car2">
<property name="name" value="#{carInfo.name}"></property>
<property name="price" value="#{carInfo.calculatorPrice()}"></property>
</bean>
<bean id="employee" class="com.itheima.spring.demo4.Employee">
<property name="name" value="#{'赵洪'}"></property>
<property name="car2" value="#{car2}"></property>
</bean>
Spring的Bean管理:(注解方式)
配置注解扫描:
<!-- Spring的注解开发:组件扫描(类上注解:可以直接使用属性注入的注解) -->
<context:component-scan base-package="com.itheima.spring.demo1"/>
Spring的Bean管理中的常用的注解:
@Component:组件(作用在类上)
@Controller :WEB层
@Service :业务层
@Repository:持久层
属性注入的注解:(使用注解注入的方式,可以不用提供set方法)
@Value :用于注入普通类型
@Autowired:自动装配:
*默认按类型进行装配
*按名称注入:
* @Qualifier:强制使用名称注入
@Resource
Bean的作用范围注解:
@Scope:
singleton:单例
prototype:多例
XML和注解的比较:
XML:可以适用任何场景。结构清晰,维护方便
注解:有些地方用不了,这个类不是自己提供的。开发方便(属性注入)
XML和注解整合开发:
XML管理Bean,注解完成属性注入
AOP:面向切面编程。AOP是OOP的扩展和延伸,解决OOP开发遇到的问题
对程序进行增强:不修改源码的情况下,AOP可以进行权限校验,日志记录,性能监控,事务控制
AOP底层实现:JDK的动态代理:只能对实现了接口的类产生代理
Cglib的动态代理:对没有实现接口的类产生代理对象。生成子类对象
Spring的基于AspectJ的AOP开发:XML的方式
编写目标类,创建接口和类
目标类的配置:
<!-- 配置目标对象:被增强的对象 -->
<bean id="orderDao" class="cn.itcast.spring.demo3.OrderDaoImpl">
</bean>
整合Junit单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3{
@Resource(name="orderDao")
private OrderDao orderDao;
@Test
public void demo1(){
productDao.save();
productDao.update();
productDao.delete();
productDao.find();
}
切入点表达式:
execution(表达式)
表达式:
[方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数)
public * cn.itcast.spring.dao.*.*(..)
编写一个切面类
public class MyAspectXml{
//前置增强
public void before(){
System.out.println("前置增强=====");
}
}
配置完成增强:
<!--配置切面类,将切面类交给Spring管理 -->
<bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>
<!-- 通过AOP的配置完成对目标类产生代理 -->
<aop:config>
<!-- 配置切入点表达式:哪些类的哪些方法需要进行增强 -->
<aop:pointcut expression="execution(* cn.itcast.spring.demo3.OrderDao.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<aop:before method="before" pointcuf-ref="pointcut1"/>
</aop:aspect>
</aop:config>
Spring使用AspectJ进行AOP的开发:
前置通知:获得切入点信息
后置通知:获得方法的返回值 after-returning
环绕通知:可以阻止目标方法的执行
Spring的AOP的基于AspectJ注解开发的方式:
编写目标类ProductDao
配置目标类:
<!-- 配置目标对象:被增强的对象 -->
<bean id="productDao" class="cn.itcast.spring.demo4.ProductDao"></bean>
<!-- 在配置文件中开启注解的AOP的开发-->
<aop:aspectj-autoproxy/>
编写切面类:
@Aspect
public class MyAspectAnno{
@Before("MyAspectAnno.pointcut1()")
public void before(){
System.out.println("前置通知====");
}
/*@Before(value="execution(* com.itcast.spring.demo4.ProductDao.save(..))")
public void before(){
System.out.println("前置增强====");
} */
@Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.save(..))")
private void pointcut1(){}
}
配置切面:
<!-- 配置切面类 -->
<bean id="myAspectAnno" class="cn.itcast.spring.demo4.MyAspectAnno"></bean>
引入外部的属性文件:
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置C3P0连接池=============================== -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置Spring的JDBC的模板========================= -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
Spring的注解的AOP的通知类型:
@Before:前置通知
@AfterReturning:后置通知
@Around:环绕通知
@AfterThrowing:异常抛出通知
@After:最终通知
JDBC模板的CRUD的操作:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
// 保存操作
public void demo1(){
jdbcTemplate.update("insert into account values (null,?,?)", "何菊花",10000d);
}
@Test
// 修改操作
public void demo2(){
jdbcTemplate.update("update account set name = ? ,money = ? where id = ?", "何巨涛",2000d,6);
}
@Test
// 删除操作
public void demo3(){
jdbcTemplate.update("delete from account where id = ?", 6);
}
@Test
// 查询操作:
public void demo4(){
String name = jdbcTemplate.queryForObject("select name from account where id = ?", String.class, 5);
System.out.println(name);
}
@Test
// 统计查询
public void demo5(){
Long count = jdbcTemplate.queryForObject("select count(*) from account", Long.class);
System.out.println(count);
}
@Test
// 封装到一个对象中
public void demo6(){
Account account = jdbcTemplate.queryForObject("select * from account where id = ?", new MyRowMapper(), 5);
System.out.println(account);
}
@Test
// 查询多条记录
public void demo7(){
List<Account> list = jdbcTemplate.query("select * from account", new MyRowMapper());
for (Account account : list) {
System.out.println(account);
}
}
class MyRowMapper implements RowMapper<Account>{
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
}
Spring进行事务管理一组API
PlatformTransactionManager:平台事务管理器
DataSourceTransactionManager:底层使用JDBC管理事务
HibernateTransactionManager:底层使用Hibernate管理事务
TransactionDefinition:事务定义信息
事务定义:用于定义事务的相关的信息,隔离级别、超时信息、传播行为、是否只读
TransactionStatus:事务的状态
事务状态:用于记录在事务管理过程中,事务的状态的对象
事务管理的API的关系:
Spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,在事务管理过程中,产生各种状态,将这些状态的信息记录到事务状态的对象中。
事务的传播行为:
保证同一个事务:
PROPAGATION_REQUIRED 支持当前事务,如果不存在,就新建一个(默认)
保证没有在同一个事务中
PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
Spring:IOC 和AOP
IOC是一个控制反转,应用场景:在项目开发当中,IOC用在容器管理当中,每个层之间的对象传递是通过Spring来管理,dao交给spring管理,service交给spring管理,控制层调用service是通过spring容器注入的
AOP是一个面向切面的编程思想,在事务管理中用到了AOP的思想,监听某一个模块的性能也用到了AOP,某个地方需要用到日志记录监听也可以用AOP
AOP的思想: