---恢复内容开始---
spring框架主要核心的部分分为两个部分:
aop:面向切面编程 不通过修改源代码,对功能进行扩张增强
ioc:控制反转 通常我们建立对象都是通过new的形式进行创建对象,但是我们这里是通过交给spring来进行创建对象
什么是spring?
spring为一个开源轻量级框架 他是一个一站式框架 对javeee的3层结构都提供了不同的技术
有什么用?
具体的用法分为ioc与aop两个方面
ioc的底层原理:
配置xml文件
dom4J进行解析
得到class路径也就是名称
通过Class类的newinstance方法创建对象
spring的bean管理(配置xml文件方式)
bean的实例化有3个方面
1.通过无参构造函数进行
2.通过静态工厂来进行创建
<bean id="factory" class="com.jdztc.ioc.Factory" factory-method="getUser"></bean>
getUser为com.jdztc.ioc.Factory类中的静态方法得到对象
3.通过实例工厂来进行创建(就是创建对象的方法不是静态方法)
首先需要进行对对象的创建否则将不能轻松的调用getUser方法
<bean id="factoryshili" class="com.jdztc.bean.FactoryShiLi" ></bean>
<bean id="bean2" factory-bean="factoryshili" factory-method="getUser"></bean>
scope属性的介绍:
他为bean的作用范围
默认值为singleton 为单实例对象
prototype:为多实例对象
request:创建对象把对象放入request中
session:创建对象把对象放入sesison中
gobleSession:创建对象把对象放入session中 具体应用:百度首页登录一次其他应用都可以使用
属性注入介绍:
向对象中的属性注入值
有3种方式:1.set方法进行注入(用的最多)
<bean id="user1" class="com.jdztc.type.User"><property name="username" value="你好"></property></bean>
<property></property>
2.有参构造函数
<!-- 属性注入(构造方法) -->
<bean id="user2" class="com.jdztc.type.UserConstructor">
<constructor-arg name="username" value="你好"></constructor-arg>
</bean>
<constructor-arg>标签
3接口注入方式(不支持)
注入复杂类型属性:
注入对象类型属性:(用的最多)
<!-- 注入对象类型属性 -->
<bean id="dao" class="com.jdztc.type.UserDao"></bean>
<bean id="service" class="com.jdztc.type.UserService">
<property name="userDao" ref="dao"/>
</bean>
P名称空间注入(一个标签不能多个相同的属性)
xmlns:p="http://www.springframework.org/schema/p" <bean id="person" class="com.jdztc.type.Person" p:pname="你不好">
注入arr数组 list集合 map集合 properties集合
arr数组的注入方式很相似
<list><value></value><l/ist>形式有多少个值就有多少个value
map集合
<map><entry key="" vlaue=""></entry></map>
properties
<props><prop key="">你好</prop></props>
ioc与dI的区别
ioc:对象的创建交给spring来创建
DI:依赖注入 给对象中的属性注入值
DI不能单独存在 ,他是建立在ioc的基础之上的
spring整合项目原理
核心配置文件的加载和对象的创建交给服务器来创建,也就是在服务器加载的时候创建
用到的ServletContext和监听器
在web.xml文件中配置
<!--配置监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--指定spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring2.xml</param-value> </context-param>
原理:使用监听器听到ServletContext创建时,进行了以下操作
1:加载核心配置文件,创建配置文件的对象
2.把配置文件的对象放入servletContext中 setAttribute()方法
3.获取配置文件对象 getAttribute()
spring的bean管理方式(注解方式实现)
导入aopjar包
开启注解扫描
对类.方法.属性都进行扫描
<context:component-scan>
只对类的属性
<context:annotation-config>
注解创建对象
@component(value="对象名")
@controller(value="") web层
@service service层 功能是一致的都能创建对象
@Repository 持久层
@scope配置范围 是单实例还是多实例对象
注解注入属性
@AutoWired 不需要set方法和类的注解的value值无关 主要是根据属性来找
@Resource value值要与类的注解的vlaue保持一致
aop方面:
原理:1.不修改原代码进行对功能的扩展2.采用横向抽取机制
横向抽取机制与纵向抽取机制
纵向抽取:
public class Fu{
publci void add(){
}
}
public Class Zi extends Fu{
public void add(){
super.add()
}
}
横向抽取机制
底层使用动态代理实现
动态代理分为:
jdk动态代理针对有接口的情况
原理:创建接口实现类的代理对象(实现InvocationHandler接口),这个对象有着与实现类相同的功能
package com.jdztc.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 针对有接口的情况,使用jdk的动态代理
* @author 付鹏鹏
*
*/
interface Fuu{
public void add();
}
public class ZhongXiangChouQuDemo implements Fuu{
//要增强的方法即切入点
@Override
public void add() {
// TODO Auto-generated method stub
//实现快速的拉屎 增强拉屎的功能
System.out.println("拉屎");
}
}
/**
* 创建与实现类相同功能的代理类
* @author 付鹏鹏
*
*/
class FuuProxy implements InvocationHandler{
private ZhongXiangChouQuDemo zhongxiang;
/**
* 覆盖其默认构造函数
*/
public FuuProxy(ZhongXiangChouQuDemo zhongxiang) {
this.zhongxiang = zhongxiang;
}
/**
* 生成实现类相同功能的代理对象
*/
public Object getProxy(){
return Proxy.newProxyInstance(zhongxiang.getClass().getClassLoader(), zhongxiang.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result=null;
System.out.println("事物的开启");
result=method.invoke(zhongxiang, args);
System.out.println("事物的结束");
return result;
}
}
具体的调用
//创建jdk动态代理类 /*ZhongXiangChouQuDemo zhongxiang=new ZhongXiangChouQuDemo(); FuuProxy proxy=new FuuProxy(zhongxiang); Fuu fuu=(Fuu) proxy.getProxy(); fuu.add();*/
cglib动态代理 针对没有接口的情况下
原理:创建子类代理对象与子类有着相同的功能(实现methodInterceptor)
package com.jdztc.aop;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import javassist.util.proxy.MethodHandler;
/**
* 没有接口的情况下 使用cglib动态代理
* @author 付鹏鹏
*
*/
class Dao{
public void add(){
System.out.println("拉屎");
}
}
public class CglibProxyDemo extends Dao{
public void add(){
System.out.println("拉屎");
}
}
/**
* 创建子类的代理对象
* @author 付鹏鹏
*
*/
class CglibProxy implements MethodInterceptor{
private Object terget;
public CglibProxy(Object terget) {
this.terget = terget;
}
public Object getIntercept(){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(terget.getClass());
//回调方法
enhancer.setCallback(this);
//创建对象
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("食物开启前");
arg3.invoke(terget, arg2);
System.out.println("事务结束了");
return null;
}
}
具体的调用
Dao cglibProxyDemo=new Dao(); CglibProxy cglibProxy=new CglibProxy(cglibProxyDemo); Dao Dao=(Dao) cglibProxy.getIntercept(); Dao.add();
上面两种方式都对方法进行了增强
aop术语:
切入点:真正被增强的方法
增强或通知:你要实现增强的逻辑
前置增强:在方法执行之前
后置增强:在方法执行之后
异常增强:在方法出现异常时执行
最终通知:在后置之后执行
环绕执行:在方法之前执行 方法之后执行也会执行
切面:将增强具体应用到切入点中的过程
这3个为常用的术语
连接点:类里面有哪些可以被增强,这些方法就是连接点
引介:动态的添加方法和属性
target(目标对象):代理目标(要增强的类)
wearing(织入):把增强应用到目标对象的过程
proxy(代理):一个类被aop织入增强后,就产生一个结果代理类
aop操作
基于aspectj的aop操作
aspectj是什么?他是面向切面的框架(把动态代理那些功能进行了封装)
实现方式:
1.基于aspectj的xml配置
2.基于aspectj的注解
引入约束
导入jar包spring-aop spring-aspectj aopaliance aspectj-weaver
使用表达式配置切入点
execution(* cn.itcase.aop.book.add(..))表示配置add切入点
execution(* cn.itcase.aop.Book.*(..))表示配置book类中所有的切入点
execution(* save*(..))匹配所有以save开头的方法
具体的应用
首先要创建对象
<!--创建两个类的对象 -->
<bean id="book" class="com.jdztc.aspectj.Book"></bean>
<bean id="mybook" class="com.jdztc.aspectj.MyBook"></bean>
aop配置
配置切入点
将增强应用到切入点中
<!--aop配置 -->
<aop:config>
<!--*后要有空格 -->
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.jdztc.aspectj.Book.*(..))" id="pointcut1"/>
<!-- 配置切面 把增强应用到方法当中的过程-->
<aop:aspect ref="mybook">
<aop:before method="before1" pointcut-ref="pointcut1"/>
<aop:around method="around" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
package com.jdztc.dao;
public class Book {
public void add(){
System.out.println("add....");
}
}
package com.jdztc.aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyBook {
public void before1(){
System.out.println("before前置增强...");
}
/**
* 环绕增强
* @throws Throwable
*/
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("方法之前");
//执行方法
proceedingJoinPoint.proceed();
System.out.println("方法之后");
}
}
log4j介绍:
info 只能看到基本信息
debug 可以看到详细的信息
基于aspectj的注解aop操作
1创建对象 2开启aop操作 在增强类中使用 在类的上面使用@Aspectj 在方法的上面使用@Before
具体的例子
<bean id="book" class="com.jdztc.dao.Book"></bean>
<!--增强类-->
<bean id="mybook" class="com.jdztc.service.MyBook"></bean>
<!--开启aop注解操作 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
package com.jdztc.service;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyBook {
//value值为切入点
@Before(value = "execution(* com.jdztc.dao.Book.*(..))")
public void before1(){
System.out.println("before1.....");
}
}
JDBCTemplate操作和使用
他与dbutil的使用很相似
dbutil操作实现查询要实现ResultSetHanlder
QueryRunner runner=new QueryRunner(dataSource);
查询对象
runner.query(sql,new BeanHanlder<User>(User.calss))
BeanHanlder为ResuleSetHanlder接口的实现类
runner.query(sql,new ResultlistHanlder<User>(User.class))
ResultListHanlder为ResultSetHanlder接口的实现类
JdbcTemplate实现查询也实现了接口RowMapper
具体的代码:
package com.jdztc.jdbctemplate;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class JdbcTemplateQuery {
/**
* jdbc模版查询返回list 使用query方法
*
*/
@Test
public void queryList(){
//创建对象
DriverManagerDataSource dataSource=new DriverManagerDataSource();
//设置数据库连接条件
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUsername("root");
dataSource.setPassword("");
//创建jdbc模版对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="select * from spring_03";
//调用模版的查询的方法queryForObject方法
List<User> list=jdbcTemplate.query(sql,new MyRowMapper());
System.out.println(list);
}
/**
* jdbc模版查询返回对象
*
*/
@Test
public void queryObject(){
//创建对象
DriverManagerDataSource dataSource=new DriverManagerDataSource();
//设置数据库连接条件
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUsername("root");
dataSource.setPassword("");
//创建jdbc模版对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="select * from spring_03 where id=?";
//调用模版的查询的方法queryForObject方法
User user=jdbcTemplate.queryForObject(sql, new MyRowMapper(), 1);
System.out.println(user);
}
/**
* 查询有多少条记录
* 查询返回某一个值 使用queryForObject方法 他的第二个参数 为返回值类型的字节码文件
*/
@Test
public void testCount(){
//创建对象
DriverManagerDataSource dataSource=new DriverManagerDataSource();
//设置数据库连接条件
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring");
dataSource.setUsername("root");
dataSource.setPassword("");
//创建jdbc模版对象
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="select count(*) from spring_03";
//调用模版的查询的方法queryForObject方法
int a=jdbcTemplate.queryForObject(sql,Integer.class);
System.out.println(a);
}
/**
* jdbc的底层代码
*/
@Test
public void query(){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet rs=null;
//加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
//建立连接
String url="jdbc:mysql://localhost:3306/spring";
String user="root";
String password="";
connection=DriverManager.getConnection(url, user, password);
String sql="select * from spring_03 where id=?";
//预编译sql语句
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,1);;
rs=preparedStatement.executeQuery();
while(rs.next()){
//System.out.println(rs.next());
User user1=new User();
String username=rs.getString("username");
String password1=rs.getString("password");
user1.setPassword(password1);
user1.setUsername(username);
System.out.println(user1);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if (connection != null) {
connection.close();
}
if (rs != null) {
rs.close();
}
if (preparedStatement != null) {
preparedStatement.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class MyRowMapper implements RowMapper<User>{
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
// TODO Auto-generated method stub
//不需要遍历结果集 这个已在JdbcTemplate中实现了
User user=new User();
String username = rs.getString("username");
String password = rs.getString("password");
user.setPassword(password);
user.setUsername(username);
return user;
}
}
c3p0连接池
记住这个ComboPooledDataSource对象
spring的事务的介绍
什么是事务?
事务是操作数据库的基本单位 指的是一组操作 这组操作要么都成功要么都失败
事务的特性
原子性:一组操作要么都成功要么都失败
一致型:操作之前之后保持一致
隔离性:多个事务操作一个数据,不影响
持久性:在数据生效后一直是那样
不考虑隔离性产生读问题
脏读 不可重复读 还有虚读
解决读问题:
设置隔离级别
事务管理器
对象platformTransactionManager
spring为不同的持久化技术提供了不同的接口实现
jdbcTemplate 和myBatis DataSourceTransactionManager
hibernate5.0 hibernateTranactionManager
如何配置事务
编程式事务管理(基本不用)
声明式事务管理 :
1 基于xml配置文件形式实现
2 注解方式实现
配置步骤:
1.配置事务管理器
2.配置事务增强
3.配置切面(aop操作)
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 配置DataSource属性 与连接池对应 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事物增强 根据事物管理器进行事务的增强 -->
<tx:advice id="aaa" transaction-manager="transactionManager">
<tx:attributes>
<!-- 设置事务操作的方法匹配规则 propagation="REQUIRED"设置事务隔离级别 -->
<tx:method name="account*"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<!--配置切入点 -->
<aop:pointcut expression="execution(* com.jdztc.service.OrderService.account(..))" id="pointcut1"/>
<!-- 将增强应用到切入点中 -->
<aop:advisor advice-ref="aaa" pointcut-ref="pointcut1"/>
</aop:config>
注解方式实现
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 配置DataSource属性 与连接池对应 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解事物 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
在你要配置事务的类的上方加上@Transactional 对类中的所有方法加上事务
ssh框架整合思想:
两个两个进行整合
struts2对spring框架进行整合
action对象交给spring进行管理
spring对hibernate进行整合
将数据库交给spring进行管理 写到spring的配置文件当中
创建sessionFactory 交给spring进行配置
---恢复内容结束---