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.通过静态工厂来进行创建
1 | < bean id="factory" class="com.jdztc.ioc.Factory" factory-method="getUser"></ bean > |
getUser为com.jdztc.ioc.Factory类中的静态方法得到对象
3.通过实例工厂来进行创建(就是创建对象的方法不是静态方法)
首先需要进行对对象的创建否则将不能轻松的调用getUser方法
1 2 | < bean id="factoryshili" class="com.jdztc.bean.FactoryShiLi" ></ bean > < bean id="bean2" factory-bean="factoryshili" factory-method="getUser"></ bean >< br > |
scope属性的介绍:
他为bean的作用范围
默认值为singleton 为单实例对象
prototype:为多实例对象
request:创建对象把对象放入request中
session:创建对象把对象放入sesison中
gobleSession:创建对象把对象放入session中 具体应用:百度首页登录一次其他应用都可以使用
属性注入介绍:
向对象中的属性注入值
有3种方式:1.set方法进行注入(用的最多)
1 | < bean id="user1" class="com.jdztc.type.User">< property name="username" value="你好"></ property ></ bean > |
<property></property>
2.有参构造函数
1 2 3 4 | <!-- 属性注入(构造方法) --> < bean id="user2" class="com.jdztc.type.UserConstructor"> < constructor-arg name="username" value="你好"></ constructor-arg > </ bean > |
<constructor-arg>标签
3接口注入方式(不支持)
注入复杂类型属性:
注入对象类型属性:(用的最多)
1 2 3 4 5 | <!-- 注入对象类型属性 --> < bean id="dao" class="com.jdztc.type.UserDao"></ bean > < bean id="service" class="com.jdztc.type.UserService"> < property name="userDao" ref="dao"/> </ bean > |
P名称空间注入(一个标签不能多个相同的属性)
1 2 | 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文件中配置
1 2 3 4 | <!--配置监听器 --> < listener > < listener-class >org.springframework.web.context.ContextLoaderListener</ listener-class > </ listener > |
1 2 3 4 5 | <!--指定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.采用横向抽取机制
横向抽取机制与纵向抽取机制
纵向抽取:
1 2 3 4 5 6 7 8 9 10 | public class Fu{ publci void add(){ } } public Class Zi extends Fu{ public void add(){ super .add() } } |
横向抽取机制
底层使用动态代理实现
动态代理分为:
jdk动态代理针对有接口的情况
原理:创建接口实现类的代理对象(实现InvocationHandler接口),这个对象有着与实现类相同的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 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; } } |
具体的调用
1 2 3 4 5 | //创建jdk动态代理类 /*ZhongXiangChouQuDemo zhongxiang=new ZhongXiangChouQuDemo(); FuuProxy proxy=new FuuProxy(zhongxiang); Fuu fuu=(Fuu) proxy.getProxy(); fuu.add();*/ |
cglib动态代理 针对没有接口的情况下
原理:创建子类代理对象与子类有着相同的功能(实现methodInterceptor)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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 ; } } |
具体的调用
1 2 3 4 | 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开头的方法
具体的应用
首先要创建对象
1 2 3 | <!--创建两个类的对象 --> <bean id= "book" class = "com.jdztc.aspectj.Book" ></bean> <bean id= "mybook" class = "com.jdztc.aspectj.MyBook" ></bean> |
aop配置
配置切入点
将增强应用到切入点中
1 2 3 4 5 6 7 8 9 10 11 | <!--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> |
1 2 3 4 5 6 7 8 | package com.jdztc.dao; public class Book { public void add(){ System.out.println( "add...." ); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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
具体的例子
1 2 3 4 5 | <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> |
1 2 3 4 5 6 7 8 9 10 11 12 | package com.jdztc.service; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class MyBook {<br> //value值为切入点 @Before (value = "execution(* com.jdztc.dao.Book.*(..))" ) public void before1(){ System.out.println( "before1....." ); } }<br> |
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
具体的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | 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操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!-- 配置事务管理器 --> <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> |
注解方式实现
1 2 3 4 5 6 7 | <!-- 配置事务管理器 --> <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进行配置
---恢复内容结束---
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步