spring框架总结
---恢复内容开始---
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进行配置
---恢复内容结束---