@author 杜勇帅
@email 820482874@qq.com
01-【熟悉】Spring框架介绍
1 Spring核心
1,AOP:面向切面编程。扩展功能而不修改源代码。
2,IOC:控制反转,降低耦合度。如果调用一个类中的方法,需要new对象然后才可以调用;在spring的IoC种,可以将代码new对象的操作交给spring的配置文件来完成。
2 一站式框架
l Spring在JavaWeb三层结果中,每一层都提供了不同的解决技术。
l Web层:SpringMVC 取代servlet
l Service层:Spring ioc
l Dao层:Spring jdbc Template 取代 jdbc
3 spring框架图
https://spring.io/
![26ca83f4614e148330353855f6fec057.png](https://img-blog.csdnimg.cn/img_convert/26ca83f4614e148330353855f6fec057.png)
02-【熟悉】重构javaEE三层结构
方式1
创建User
![3dd61d45ca1651c2f1771c7265211832.png](https://img-blog.csdnimg.cn/img_convert/3dd61d45ca1651c2f1771c7265211832.png)
创建UserService
![0d917b541d2dcb2947b28a89faede17d.png](https://img-blog.csdnimg.cn/img_convert/0d917b541d2dcb2947b28a89faede17d.png)
创建UserServiceImpl
![e578a808f65261af103cdda0c81de09b.png](https://img-blog.csdnimg.cn/img_convert/e578a808f65261af103cdda0c81de09b.png)
创建UserDao
![4b6b7ef5f1b454c8fd26183622eba3ec.png](https://img-blog.csdnimg.cn/img_convert/4b6b7ef5f1b454c8fd26183622eba3ec.png)
创建UserDaoImpl
![be0815176a0d57285c64491e8641e28c.png](https://img-blog.csdnimg.cn/img_convert/be0815176a0d57285c64491e8641e28c.png)
创建UserAction
![61d53668d34b5291d3bcbe9df32ae9e1.png](https://img-blog.csdnimg.cn/img_convert/61d53668d34b5291d3bcbe9df32ae9e1.png)
测试
![1d731bd1070a4a43d2300f48875ac54c.png](https://img-blog.csdnimg.cn/img_convert/1d731bd1070a4a43d2300f48875ac54c.png)
总结及存在问题
所有的使用者都是主动在类里面去new的其它类的对象。所有一但其它类发生变化,所有使用者都要根着变
方式2
创建UserFactory
![6e16c59e519f55566d844f4dede0a40b.png](https://img-blog.csdnimg.cn/img_convert/6e16c59e519f55566d844f4dede0a40b.png)
修改UserServlet
![301ee9996ae767bcbcf1fc0aa8b28bf9.png](https://img-blog.csdnimg.cn/img_convert/301ee9996ae767bcbcf1fc0aa8b28bf9.png)
修改UserServiceImpl
![cee52d9367812a13f0b451babf8cb897.png](https://img-blog.csdnimg.cn/img_convert/cee52d9367812a13f0b451babf8cb897.png)
总结及存在问题
以上的写法发现工厂类会越来越多,所以我们一般使用反射去创建对象
方式3
创建bean.properties
![615b95c04913bb599fa78010145e222e.png](https://img-blog.csdnimg.cn/img_convert/615b95c04913bb599fa78010145e222e.png)
修改BeanFactory
/**
* 对象工厂
* @author LJH
*
*/
public class BeanFactory {
/**
* 加载bean.properties
* @param key
* @return
*/
static Properties properties=new Properties();
static {
InputStream inStream=BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
properties.load(inStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static <T> T getInstance(String key){
try {
//根据key找到完全限定名
String clzz=properties.getProperty(key);
if(null!=clzz) {
//加载类
Class<?> cls = Class.forName(clzz);
return (T) cls.newInstance();
}else {
System.err.println("key不存在");
return null;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
修改UserServlet
![eb01a2deabed21c9ca625e0c54ed7431.png](https://img-blog.csdnimg.cn/img_convert/eb01a2deabed21c9ca625e0c54ed7431.png)
修改UserServiceImpl
![658f1e2a0460dd923643a12df32da873.png](https://img-blog.csdnimg.cn/img_convert/658f1e2a0460dd923643a12df32da873.png)
03-【掌握】IOC/DI解耦合及实现原理
解释说明IOC/DI
控制反转(Inversion of Control,缩写为IoC)
(Dependency Injection,简称DI)
1,知识拓扑图
![360024f026ed2f48a561dcd6915fedfa.png](https://img-blog.csdnimg.cn/img_convert/360024f026ed2f48a561dcd6915fedfa.png)
2,相关概念说明
1.控制反转 --> 谁控制谁? 控制什么? 为何叫反转(对应于正向)?哪些方面反转了?为何需要反转?
谁控制谁? --> IoC/DI容器控制应用程序
控制什么? --> IoC/DI容器控制对象本身的创建、实例化; IoC/DI容器控制对象之间的依赖关系
为何叫反转(对应于正向)? --> 因为现在应用程序不能主动去获取外部资源了,而是被动等待IoC/DI容器给它注入它所需要的资源,所以称之为反转.
哪些方面反转了? --> 1.创建对象 2.程序获取资源的方式反了
为何需要反转? --> 1.引入IoC/DI容器过后,体系更为松散,而且管理更有序; 2.类之间真正实现了松散耦合
2.依赖 --> 什么是依赖(按名称理解、按动词理解)? 谁依赖于谁? 为什么需要依赖? 依赖什么东西?
什么是依赖(按名称理解、按动词理解)? --> 依赖(按名称理解):依赖关系; 依赖(按动词理解):依赖的动作
谁依赖于谁? --> 应用程序依赖于IoC/DI容器
为什么需要依赖? --> 因为发生了反转,应用程序依赖的资源都是IoC/DI容器里面
依赖什么东西? --> 应用程序依赖于IoC/DI容器,依赖IoC/DI容器为它注入所需要的资源。(比如:依赖关系)
3.注入:谁注入于谁? 注入什么东西? 为何要注入?
谁注入于谁? --> IoC/DI容器注入于应用程序
注入什么东西? --> 注入应用程序需要的外部资源,比如依赖关系
为何要注入? --> 因为程序要正常运行需要这些外部资源
4.依赖注入和控制反转是同一概念吗?
不是同一概念, 其实它们两个描述的是同一件事件,但是是从不同的角度来说:控制反转是从IoC/DI容器的角度;依赖注入是从应用程序的角度
控制反转的描述: IoC/DI容器反过来控制应用程序,控制应用程序锁所需要的外部资源(比如:外部资源)
依赖注入的描述: 应用程序依赖IoC/DI容器,依赖它注入所需要的外部资源。
5.参与者都有哪些?
IoC/DI容器、应用程序
6.IoC/DI是什么?能做什么?怎么做?用在什么地方?
IoC/DI是什么?
IoC(Inversion of Control):就是使用IoC/DI容器反过来控制应用程序所需要的外部资源,是程序开发思想。
DI(Dependency Injection):就是应用程序依赖IoC/DI容器来注入所需要的外部资源,也是程序的开发思想。
能做什么? --> 松散耦合对象
怎么做? --> 使用Spring框架,里面有实现好了的IoC/DI容器
用在什么地方? --> 凡是程序里面需要使用外部资源的情况,都可以考虑使用IoC/DI容器
7.什么是外部资源
对于一个类来讲,所谓的外部资源,就是指在自己类的内部不能得到或实现的东西,比如说:在类里面需要读取一个配置文件,那么这个配置文件就相当于这个类的外部资源。又比如:A类里面要调用B类,那么对于A类来讲B类就是外部资源。
8. IoC容器
简单的理解就是:实现IoC思想,并提供对象创建、对象装配以及对象生命周期管理的软件就是IoC容器。
对IoC的理解:
a. 应用程序无需主动new对象,而是描述对象应该如何被创建
b. 应用程序不需要主动装配对象之间的依赖关系,而是描述需要哪个服务,IoC容器会帮你装配,被动接受装配
c. 主动变被动,是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则
9.使用IoC/DI容器开发需要改变思路
a. 应用程序不主动创建对象,但是要描述创建它们的方式
b. 在应用程序代码中不直接进行服务的装配,但是要描述哪一个组件需要哪一项服务,由容器负责将这些装配在一起。也就是说:所有的组件都是被动的,组件初始化和专供都是由容器负责,应用程序只是在获取相应的组件后,实现应用的功能即可。
1,看到new对象就要考虑使用IOC容器
2,看到对象里面需要属性就应该想到使用DI
|--成员属性
class A{
User user =new User();
public void a(){
User user=new User();
}
}
3,IOC和DI使用的底层技术
−Xml配置文件
−dom4j解析xml
−工厂设计模式
−反射
4,最终目地
程序的高内聚,低耦合
04-【掌握】spring的入门配置
下载
https://spring.io/
![ce1d947a3c3fad04d87fcd33fe8d11bf.png](https://img-blog.csdnimg.cn/img_convert/ce1d947a3c3fad04d87fcd33fe8d11bf.png)
![2f054a4d65e99591c4b3fe8fe5be1259.png](https://img-blog.csdnimg.cn/img_convert/2f054a4d65e99591c4b3fe8fe5be1259.png)
![2d49bfc6c4ebaa4345aac0e765d77cae.png](https://img-blog.csdnimg.cn/img_convert/2d49bfc6c4ebaa4345aac0e765d77cae.png)
![aabb802cddca83f9ef5217822a0866e6.png](https://img-blog.csdnimg.cn/img_convert/aabb802cddca83f9ef5217822a0866e6.png)
![9dee2d664133198e88283f4cd08f29e3.png](https://img-blog.csdnimg.cn/img_convert/9dee2d664133198e88283f4cd08f29e3.png)
![4a40565501e0ec80ae37b8755badb00a.png](https://img-blog.csdnimg.cn/img_convert/4a40565501e0ec80ae37b8755badb00a.png)
![af6fa5f02a73414b9d36aa49e864012e.png](https://img-blog.csdnimg.cn/img_convert/af6fa5f02a73414b9d36aa49e864012e.png)
![6e7a555bb1128f24249475b33a1e3343.png](https://img-blog.csdnimg.cn/img_convert/6e7a555bb1128f24249475b33a1e3343.png)
![53d116e0145f17b698bf1a6d7fe7b709.png](https://img-blog.csdnimg.cn/img_convert/53d116e0145f17b698bf1a6d7fe7b709.png)
![6218c1fa97d3aadee7cacf4a49d373f5.png](https://img-blog.csdnimg.cn/img_convert/6218c1fa97d3aadee7cacf4a49d373f5.png)
![8ab7b70d1e38281692e2b85ca2a97672.png](https://img-blog.csdnimg.cn/img_convert/8ab7b70d1e38281692e2b85ca2a97672.png)
![4d6a354740fa2489bbad8f30f8e439ff.png](https://img-blog.csdnimg.cn/img_convert/4d6a354740fa2489bbad8f30f8e439ff.png)
下载文件说明
![b5fdaee817567c463087a2f0204de8ce.png](https://img-blog.csdnimg.cn/img_convert/b5fdaee817567c463087a2f0204de8ce.png)
docs文档
libs jar包
schema头文件
jar包说明
spring-aop-4.3.24.RELEASE.jar 面向切面编程的包
spring-aspects-4.3.24.RELEASE.jar 面向切面编程的包aspects这个包是spring集成的其它框架的包aspects是一个开源的AOP框架
spring-beans-4.3.24.RELEASE.jar 工厂包 bean工厂
spring-context-4.3.24.RELEASE.jar 上下文包
spring-context-support-4.3.24.RELEASE.jar上下文辅助包
spring-core-4.3.24.RELEASE.jar 核心包
spring-expression-4.3.24.RELEASE.jar 表达式
spring-instrument-4.3.24.RELEASE.jar 辅助包
spring-instrument-tomcat-4.3.24.RELEASE.jar 辅助包
spring-jdbc-4.3.24.RELEASE.jar 数据库JDBC的访问包
spring-jms-4.3.24.RELEASE.jar 消息中间件包
spring-messaging-4.3.24.RELEASE.jar 消息中间件包
spring-orm-4.3.24.RELEASE.jar 集成第三方的ORM框架的包 如hibernate mybatis
spring-oxm-4.3.24.RELEASE.jar
spring-test-4.3.24.RELEASE.jar
spring-tx-4.3.24.RELEASE.jar 事务处理包
spring-web-4.3.24.RELEASE.jar 集成struts或springmvc的web开发环境需要的包
spring-webmvc-4.3.24.RELEASE.jar springmvc的包
spring-webmvc-portlet-4.3.24.RELEASE.jar spring对 portlet 的支持包
spring-websocket-4.3.24.RELEASE.jar 网页聊天的包
创建项目和User
![907f5d9bce1e8018a87b0dfd9d6db549.png](https://img-blog.csdnimg.cn/img_convert/907f5d9bce1e8018a87b0dfd9d6db549.png)
导入jar
spring
![c523e1d823f3e0d27a1cab9c058f32ec.png](https://img-blog.csdnimg.cn/img_convert/c523e1d823f3e0d27a1cab9c058f32ec.png)
log4j
![1b9c2b9edfefdae291f6d448c95d8739.png](https://img-blog.csdnimg.cn/img_convert/1b9c2b9edfefdae291f6d448c95d8739.png)
创建log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
创建applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 声明了一个对象 -->
<bean id="user" class="com.sxt.domain.User">
<property name="id" value="1"></property>
<property name="name" value="小明"></property>
<property name="address" value="武汉"></property>
</bean>
<!-- user com.sxt.domain.User
user2 com.sxt.domain.User
-->
<bean id="user2" class="com.sxt.domain.User">
<property name="id" value="2"></property>
<property name="name" value="小明"></property>
<property name="address" value="武汉"></property>
</bean>
</beans>
测试
![3b46885c580c9c3c88df47823955fcd1.png](https://img-blog.csdnimg.cn/img_convert/3b46885c580c9c3c88df47823955fcd1.png)
05-【掌握】Spring相关配置详解
1,Bean标签
1,bean标签id属性:为Bean标签自定义名称,但是不能使用特殊符号。在代码中可以根据id值获取到对象
2,bean标签class属性:代表对应类的全路径
3,bean标签scope属性:
singleton:默认值,表示单例
prototype:多例
request:WEB项目中,Spring创建一个Bean对象,将Bean对象放入request域中。
session:WEB项目中,Spring创建一个Bean对象,将Bean对象放入session域中。
4,bean标签lazy属性
默认情况下启动程序时对象就直接创建了
当加入lazy-init=“true”之后使用者取对象时才会创建
2,Spring实例化Bean的三种方式【了解】
1,使用类中的无参构造方法【重点掌握】
![59490156ab16412deeae40f5b7f9fc36.png](https://img-blog.csdnimg.cn/img_convert/59490156ab16412deeae40f5b7f9fc36.png)
2,使用静态工厂【掌握】
创建BeanFactory
![7362011771bcc5f014fa9dbf44bbce0b.png](https://img-blog.csdnimg.cn/img_convert/7362011771bcc5f014fa9dbf44bbce0b.png)
修改applicationContext.xml
![9000711b45040c1b190bf2ab2078755d.png](https://img-blog.csdnimg.cn/img_convert/9000711b45040c1b190bf2ab2078755d.png)
3,使用实例工厂【掌握】
修改BeanFactory
![a194a27fef7e780362912bc4a04da252.png](https://img-blog.csdnimg.cn/img_convert/a194a27fef7e780362912bc4a04da252.png)
修改applicationContext.xml
![25b62fac4a3b98aeeae5f53ce997a016.png](https://img-blog.csdnimg.cn/img_convert/25b62fac4a3b98aeeae5f53ce997a016.png)
3,Bean属性注入
使用getset方法
创建User
![f72616a4a39e9f09d8cc76651952936a.png](https://img-blog.csdnimg.cn/img_convert/f72616a4a39e9f09d8cc76651952936a.png)
修改applicationContext.xml
![66da17e1251867cbc241c3084073cab5.png](https://img-blog.csdnimg.cn/img_convert/66da17e1251867cbc241c3084073cab5.png)
使用有参的构造方法
![b4a3e9922dbb3cd1bdac7e3ff7cfc317.png](https://img-blog.csdnimg.cn/img_convert/b4a3e9922dbb3cd1bdac7e3ff7cfc317.png)
![ac555ed372326b8f8427eb2d172f1af5.png](https://img-blog.csdnimg.cn/img_convert/ac555ed372326b8f8427eb2d172f1af5.png)
其它非常规属性的注入
创建Person
![b9a4e892a1ee2e070d72f342e0ab3201.png](https://img-blog.csdnimg.cn/img_convert/b9a4e892a1ee2e070d72f342e0ab3201.png)
数组的注入
![030b2bf686b958468face2ae7908f2af.png](https://img-blog.csdnimg.cn/img_convert/030b2bf686b958468face2ae7908f2af.png)
List集合的注入
<!-- list的注入 private List<String> listStrs;-->
<property name="listStrs">
<!-- <array>
<value>武汉1</value>
<value>武汉2</value>
<value>武汉3</value>
</array> -->
<list>
<value>武汉1</value>
<value>武汉2</value>
<value>武汉3</value>
</list>
</property>
<!-- list的注入 private List<User> listUsers; -->
<property name="listUsers">
<list>
<bean class="com.sxt.domain.User">
<constructor-arg index="0" value="1" type="java.lang.Integer"></constructor-arg>
<constructor-arg index="1" value="小明" type="java.lang.String"></constructor-arg>
</bean>
<!-- 引入ioc容器里面的其它对象 -->
<ref bean="user4"/>
</list>
</property>
<!-- list的注入 private List<Map<String,String>> listMaps;-->
<property name="listMaps">
<list>
<map>
<entry key="s1" value="s1" ></entry>
<entry key="s2" value="s2" ></entry>
</map>
</list>
</property>
set集合的注入
里面元素不重复
![37d839ac443a033fb41b40855f7c0599.png](https://img-blog.csdnimg.cn/img_convert/37d839ac443a033fb41b40855f7c0599.png)
map集合的注入
![13a028ce96588f85ae394c12a67ca531.png](https://img-blog.csdnimg.cn/img_convert/13a028ce96588f85ae394c12a67ca531.png)
properties的注入
![5cc30de7b6b5125d45b2bae395780d10.png](https://img-blog.csdnimg.cn/img_convert/5cc30de7b6b5125d45b2bae395780d10.png)
外部的properties的注入
创建db.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=123456
引入约束文件
![f9d4093710f720eb61d0a4cb7590e171.png](https://img-blog.csdnimg.cn/img_convert/f9d4093710f720eb61d0a4cb7590e171.png)
修改applicationContext.xml
![876550f90d36716a9955ec7a6914cf94.png](https://img-blog.csdnimg.cn/img_convert/876550f90d36716a9955ec7a6914cf94.png)
06-【熟悉】XML方式重构三层结构
创建项目导包
![0d479a82f735a54348411ff36e80f8ae.png](https://img-blog.csdnimg.cn/img_convert/0d479a82f735a54348411ff36e80f8ae.png)
创建log4j.properties
创建User
![17935d2dc52ec26e652a52e92db5d13c.png](https://img-blog.csdnimg.cn/img_convert/17935d2dc52ec26e652a52e92db5d13c.png)
创建UserDao
![142401d8aa415db9344b1f22e4336bac.png](https://img-blog.csdnimg.cn/img_convert/142401d8aa415db9344b1f22e4336bac.png)
创建UserDaoImpl
![28164a4a3d9b04598e05be4cb8b6f173.png](https://img-blog.csdnimg.cn/img_convert/28164a4a3d9b04598e05be4cb8b6f173.png)
创建UserService
![43b20e3e673cfa57c965f99f62050a82.png](https://img-blog.csdnimg.cn/img_convert/43b20e3e673cfa57c965f99f62050a82.png)
创建UserServiceImpl
![613ba6a228b8f574acad452eab8c693a.png](https://img-blog.csdnimg.cn/img_convert/613ba6a228b8f574acad452eab8c693a.png)
创建UserServlet
![138fdf25285d41f10040da0e8687491d.png](https://img-blog.csdnimg.cn/img_convert/138fdf25285d41f10040da0e8687491d.png)
创建applicationContext.xml
![dfa7571d1e411334dbdb670cf75bc1e1.png](https://img-blog.csdnimg.cn/img_convert/dfa7571d1e411334dbdb670cf75bc1e1.png)
测试
![e1b9f644a4758e9fc28f77d4d6d4583f.png](https://img-blog.csdnimg.cn/img_convert/e1b9f644a4758e9fc28f77d4d6d4583f.png)
自动装配的配置
![81e51202a03fd45acaea198e40ba401a.png](https://img-blog.csdnimg.cn/img_convert/81e51202a03fd45acaea198e40ba401a.png)
autowire
|--byName 根据对象里面的属性名去IOC容器里面找对应id的对象
|--byType 根据对象里面属性的类型去IOC容器里面找对象
拆分配置文件
![6a31df3916695fa924e514ad134c7ff2.png](https://img-blog.csdnimg.cn/img_convert/6a31df3916695fa924e514ad134c7ff2.png)
![fdbaa2e3d6f350a45053caf9067e7d30.png](https://img-blog.csdnimg.cn/img_convert/fdbaa2e3d6f350a45053caf9067e7d30.png)
07-【掌握】注解方式重构三层结构
修改UserServlet
![e514017ab90b0e3d042afd6b9bbf28fd.png](https://img-blog.csdnimg.cn/img_convert/e514017ab90b0e3d042afd6b9bbf28fd.png)
修改UserServiceImpl
![516be8e4948918c4a0eaca8ffc8894de.png](https://img-blog.csdnimg.cn/img_convert/516be8e4948918c4a0eaca8ffc8894de.png)
修改UserDaoImpl
![be52db94179560390f014549b9b0ae96.png](https://img-blog.csdnimg.cn/img_convert/be52db94179560390f014549b9b0ae96.png)
修改UserDaoImpl
![f2b5c19ea279d29f77b52e36d7b8cc6b.png](https://img-blog.csdnimg.cn/img_convert/f2b5c19ea279d29f77b52e36d7b8cc6b.png)
总结
@Component 代表一个spring的组件
@Controller 被Component 注解了。主要作用于接收用户请求的类
@Service 被Component 注解了 主要作用于服务层
@Repository 被Component 注解了 主要作用于数据访问层
@Autowired 作用于类里面的属性或方法 用于自动从IOC容器里面根据类型去装配
|--byType
![c50a9991fbf9bd1ec769c3094e657d9b.png](https://img-blog.csdnimg.cn/img_convert/c50a9991fbf9bd1ec769c3094e657d9b.png)
08-【熟悉】AOP的概述
1,什么是AOP
AOP(Aspect Oriented Programing)面向切面编程。
AOP采取横向抽取机制,取代了传统的继承纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)
Spring的AOP采用了纯Java实现,不需要专门的编译过程和类加载器,在运行期间通过动态代理的方式向目标类注入增强代码。
2,AOP应用场景说明
举例实际项目的引用场景
对程序进行增强:不修改源码的情况下.
权限校验,日志记录,性能监控,事务控制.
3,AOP的底层实现
代理机制:
Spring的AOP的底层用到两种代理机制:
JDK的动态代理 :针对实现了接口的类产生代理.
Cglib的动态代理 :针对没有实现接口的类产生代理
09-【掌握】代理模式
代理模式概述
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.
这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法
举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理人(经纪人)来解决.这就是代理思想在现实中的一个例子
![e5f407dbeef462bfdab9b82c1a6211be.png](https://img-blog.csdnimg.cn/img_convert/e5f407dbeef462bfdab9b82c1a6211be.png)
代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象
分类
静态代理
动态代理
|--JDK的动态代理
|--CGLIB的动态代理
静态代理
创建Man
![e8ad36db405c1f382311c60f7aaac13f.png](https://img-blog.csdnimg.cn/img_convert/e8ad36db405c1f382311c60f7aaac13f.png)
创建ManProxy
![db0c8659b8ebdd8ef330fabc4add9a64.png](https://img-blog.csdnimg.cn/img_convert/db0c8659b8ebdd8ef330fabc4add9a64.png)
创建TestProxy
![cc55dc556c4cae75e716989d69da6006.png](https://img-blog.csdnimg.cn/img_convert/cc55dc556c4cae75e716989d69da6006.png)
总结
1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.
2.缺点:
因为一个目录类对应一个代理类 会有很多代理类,类太多.同时,
如何解决静态代理中的缺点呢?答案是可以使用动态代理方式
4,动态代理[Dynamic proxy]-JDK代理
动态代理有以下特点:
1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理
JDK动态代理实现前提:目标类必须实现一个或多个接口
创建Man
![3b1dc6f2116a3c04d91fd86bd92d85ac.png](https://img-blog.csdnimg.cn/img_convert/3b1dc6f2116a3c04d91fd86bd92d85ac.png)
创建Eat
![b2e6626716bdb5fd4e1084d3667af2e7.png](https://img-blog.csdnimg.cn/img_convert/b2e6626716bdb5fd4e1084d3667af2e7.png)
创建Sleep
![f0c906b8783c013c0de49c9a2760a072.png](https://img-blog.csdnimg.cn/img_convert/f0c906b8783c013c0de49c9a2760a072.png)
创建ProxyFactory
public class ProxyFactory {
// 声明目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/**
* 创建代理对象
*/
public Object newProxyInstance() {
/**
* 参数1:当前程序的类加载器
* 参数2:目标对象的所有接口的数组
* 参数3:执行目标对象的一个执行实例
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 参数1:代理对象
* 参数2:要执行的目标对象的方法
* 参数3:执行目标对象的方法的参数列表
*/
@Override
public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject)
throws Throwable {
before();
//执行目标方法
// System.out.println(paramObject.toString());
Object object = paramMethod.invoke(target, paramArrayOfObject);
after();
return object;
}
});
}
/**
* 前置通知
*/
public void before() {
System.out.println("喝酒");
}
/**
* 后置通知
*/
public void after() {
System.out.println("搞一根");
}
}
总结
1,目标类必须至少 实现一个接口
2,代理对象只能强转成目标对象的接口类型
3,目标对象里面的自定义的方法不能被调用
代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能使用JDK动态代理
5,动态代理[Dynamic proxy]-CGLIB代理
JDK的动态代理目标类必须要实现至少一个接口,并且目标类里面非接口的方法不能被调用
上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理
Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想目标没有实现接口的类,就可以使用Cglib实现.
Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.
Cglib子类代理实现方法:
1.需要引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-3.2.5.jar即可.
2.引入功能包后,就可以在内存中动态构建子类
3.代理的类不能为final,否则报错
4.目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.
导入jar包
![2461763c38785dfcccbe9f316f8cb899.png](https://img-blog.csdnimg.cn/img_convert/2461763c38785dfcccbe9f316f8cb899.png)
创建Man
![d5d5fdd1a8f55c617c122851d6c26f9d.png](https://img-blog.csdnimg.cn/img_convert/d5d5fdd1a8f55c617c122851d6c26f9d.png)
创建ProxyFactory
public class ProxyFactory implements MethodInterceptor{
// 声明目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/**
* 构造代理对象
*/
public Object getProxyInstance() {
//1.工具类
Enhancer enhancer=new Enhancer();
//设置父类 目标对象
enhancer.setSuperclass(target.getClass());
//设置回调
enhancer.setCallback(this);
//创建代理类及子节码
return enhancer.create();
}
/**
* 参数1 :代理对象
* 参数2:目标方法
* 参数3:目标方法的参数
* 参数4:方法的代理
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
before();
//执行目标方法
Object object = method.invoke(target, args);
after();
return object;
}
/**
* 前置通知
*/
public void before() {
System.out.println("喝酒");
}
/**
* 后置通知
*/
public void after() {
System.out.println("搞一根");
}
}
测试
![415fbba32e8ff99451637e1b37605a4c.png](https://img-blog.csdnimg.cn/img_convert/415fbba32e8ff99451637e1b37605a4c.png)
6,在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用JDK代理
如果目标对象没有实现接口,用Cglib代理
10-【掌握】普通AOP开发(XML方式)
AOP开发中的概念
1,JoinPoint(连接点):所谓连接点是指那些被拦截的点,而spring中这些点就是指方法,因为spring只支持方法类型的连接点。
2,PointCut(切入点):所谓切入点就是指我们要对那些JoinPoint进行拦截的定义。
3,Advice(通知/增强):所谓通知/增强,就是指拦截到JoinPoint后需要完成的事情。他分为前置通知/增强,后置通知/增强,异常通知/增强,最终通知/增强,环绕
通知/增强(切面要完成的功能);
4,Introduction(引介):引介是一种特殊的Advice,在不修改代码的前提下,引介可以在运行期为类动态的添加一些方法或Field。
5,Target(目标):代理对象的目标对象(要增强的类)
6,Weaving(织入):把Advice应用到Target的过程
7,Proxy(代理):一个类被AOP注入增强后,就产生了一个结果代理类
8,Aspect(切面):是PointCut和Advice(Introduction)的结合
![f00a1aafe76ae8811c486973ba473fd7.png](https://img-blog.csdnimg.cn/img_convert/f00a1aafe76ae8811c486973ba473fd7.png)
spring AOP开发准备工作
创建项目
![9555817a021a856d6ac9773b7427a046.png](https://img-blog.csdnimg.cn/img_convert/9555817a021a856d6ac9773b7427a046.png)
导包
![4afdb26cc59aed764a8d8173d9e1fc3c.png](https://img-blog.csdnimg.cn/img_convert/4afdb26cc59aed764a8d8173d9e1fc3c.png)
创建Man
![d1bf30c3c899d80f1a5975d51204519c.png](https://img-blog.csdnimg.cn/img_convert/d1bf30c3c899d80f1a5975d51204519c.png)
创建applicationContext.xml
![906f67ff8f12e7166f5322f03058097c.png](https://img-blog.csdnimg.cn/img_convert/906f67ff8f12e7166f5322f03058097c.png)
![8a265fb816d606a935e0ef217581ca7a.png](https://img-blog.csdnimg.cn/img_convert/8a265fb816d606a935e0ef217581ca7a.png)
创建log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
spring AOP实现前置通知
创建MyBeforeAdvise
![c86f4f7824dc6469d40c58fea574e3e3.png](https://img-blog.csdnimg.cn/img_convert/c86f4f7824dc6469d40c58fea574e3e3.png)
配置applicationContext.xml
![f796017aae0c213efec526991a23060a.png](https://img-blog.csdnimg.cn/img_convert/f796017aae0c213efec526991a23060a.png)
测试
![e532b2c1b2ef71bc43def2c03ca59014.png](https://img-blog.csdnimg.cn/img_convert/e532b2c1b2ef71bc43def2c03ca59014.png)
spring AOP实现后置通知
创建MyAfterAdvise
![a45291e4df5be406ebb203c2a975bac2.png](https://img-blog.csdnimg.cn/img_convert/a45291e4df5be406ebb203c2a975bac2.png)
修改applicationContext.xml
![5fcd6bc165dabce40a2c6582eb569ebf.png](https://img-blog.csdnimg.cn/img_convert/5fcd6bc165dabce40a2c6582eb569ebf.png)
spring AOP实现环绕通知
创建MyAroundAdvise
![d1173cea0b30135ae489a439ccb97cd2.png](https://img-blog.csdnimg.cn/img_convert/d1173cea0b30135ae489a439ccb97cd2.png)
修改applicationContext.xml
![4d58847640c4651c2cff087a12211adb.png](https://img-blog.csdnimg.cn/img_convert/4d58847640c4651c2cff087a12211adb.png)
spring AOP实现异常通知
创建MyExceptionAdvise
![8a6051604089a31dd94bef11ebc769aa.png](https://img-blog.csdnimg.cn/img_convert/8a6051604089a31dd94bef11ebc769aa.png)
修改applicationContext.xml
![e6a0fa0f1ec0fa70b41135746769ccdf.png](https://img-blog.csdnimg.cn/img_convert/e6a0fa0f1ec0fa70b41135746769ccdf.png)
11-【掌握】使用AspectJ AOP开发(XML方式)
1,AspectJ介绍
1,什么是aspectJ
AspectJ是一个基于Java语言的AOP框架,Spring2.0开始引入对AspectJ的支持,AspectJ扩展了Java语言,提供了专门的编译器,在编译时提供了横向代码的注入。
@AspectJ是AspectJ1.5新增功能,通过JDK1.5注解技术,允许直接在Bean中定义切面
新版本的Spring中,建议使用AspectJ方式开发AOP
2,aspectJ开发两种方式
基于xml配置文件方式开发
基于注解方式的开发
2,创建Man
![19cd7e2dd59daa29651fd84e894e5307.png](https://img-blog.csdnimg.cn/img_convert/19cd7e2dd59daa29651fd84e894e5307.png)
3,创建MyAdvise
public class MyAdvise {
/**
* 前置通知
*/
public void before() {
System.out.println("前置通知");
}
/**
* 后置通知
*/
public void after() {
System.out.println("后置通知");
}
/**
* 环绕通知
*/
public void around(ProceedingJoinPoint point) {
before();
try {
point.proceed();//执行目标方法
} catch (Throwable e) {
e.printStackTrace();
}
after();
}
/**
* 异常通知
*
*/
public void error(Throwable tw) {
System.out.println("产生异常:"+tw.getMessage());
}
}
4,配置applicationContext.xml
![a6c0dd4870c5cbd33793d021742691fa.png](https://img-blog.csdnimg.cn/img_convert/a6c0dd4870c5cbd33793d021742691fa.png)
12-【熟悉】AOP开发(注解方式)
创建MyAdvise
@Component //让spring的IOC容器创建对象
@Aspect //告诉spring这个类是一个切面类
@EnableAspectJAutoProxy //开启切面的注解配置 取代xml<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
public class MyAdvise {
/**
* 声明切入点
*
*/
@Pointcut(value="execution(* com.sxt.domain.*.*(..))")
public void pc() {
}
/**
* 前置通知
*/
// @Before("execution(* com.sxt.domain.*.*(..))")
@Before(value="pc()")
public void before() {
System.out.println("前置通知");
}
/**
* 后置通知
*/
//@After("execution(* com.sxt.domain.*.*(..))")
//@After(value="pc()")
public void after() {
System.out.println("后置通知");
}
/**
* 环绕通知
*/
//@Around("execution(* com.sxt.domain.*.*(..))")
//@Around(value="pc()")
public void around(ProceedingJoinPoint point) {
before();
try {
point.proceed();//执行目标方法
} catch (Throwable e) {
e.printStackTrace();
}
after();
}
/**
* 异常通知
*
*/
// @AfterThrowing(value="execution(* com.sxt.domain.*.*(..))",throwing="tw")
//@AfterThrowing(value="pc()",throwing="tw")
public void error(Throwable tw) {
System.out.println("产生异常:"+tw.getMessage());
}
}
修改applicationContext.xml
![2359540e6f088d473826b881a4179e19.png](https://img-blog.csdnimg.cn/img_convert/2359540e6f088d473826b881a4179e19.png)
13-【熟悉】Spring-JdbcTemplate
Spring对不同的持久化支持
Spring为各种支持的持久化技术,都提供了简单操作的模板和回调
ORM持久化技术
模板类
JDBC
org.springframework.jdbc.core.JdbcTemplate
Hibernate5.0
Org.springframework.orm.hibernate5.HibernateTemplate
ibatis(MyBatis)
org.springframework.orm.ibatis.sqlMapClientTemplate
JPA
org.springframework.orm.jpa.JpaTemplate
其实Spring的JDBCTemplate有点像DBUtils,但是有时候还没有DBUitls好用。这里来学习一下使用Spring的JDBCTemplate来玩一下CRUD。
创建项目并导包
![e6736903e11f7d2101d1aa0ec560ef09.png](https://img-blog.csdnimg.cn/img_convert/e6736903e11f7d2101d1aa0ec560ef09.png)
数据库的访问驱动包
![a6614b40670a53264d5a3e0e1b374987.png](https://img-blog.csdnimg.cn/img_convert/a6614b40670a53264d5a3e0e1b374987.png)
JdbcTemplate使用的基本步骤
然后再看看Spring的JDBCTemplate的使用大体步骤
① 第一步 创建对象设置数据库的信息
② 第二步 创建jdbcTemplate对象,设置数据源
③ 第三步 调用jdbcTemplate对象中的方法
![205ac8658a452f0dfd0ecbf4284220da.png](https://img-blog.csdnimg.cn/img_convert/205ac8658a452f0dfd0ecbf4284220da.png)
![b241e5d9f930657127f0b90285a945ef.png](https://img-blog.csdnimg.cn/img_convert/b241e5d9f930657127f0b90285a945ef.png)
4、使用IOC和DI去完成上面的程序xml
其实这个例子本身没有什么的,只是演示了一下,其实在学Spring之后,感觉应该形成一种习惯,在new对象的时候我要想到IOC,在使用Set方法的时候,我要想到DI。切面编程我们应该想到用AOP的。这里可以在Spring中配置如下的引用链:
1. 我要有DataSource,DataSource的属性可以通过注入数据库的一些配置属性添加
2. 我要有JdbcTemplate,而Template依赖与DataSource,我要以ref的方式为我的JdbcTemplate注入引用
3. 有了JdbcTemplate之后,我要有Dao,此时我应该在Dao添加一个JdbcTemplate的成员,然后以ref的方式将JdbcTemplate引入到Dao中
4. 我在Action或者是Servlet中都会调用的是Serivce,所以,我在Serivce中要添加一个Dao作为成员,然后由ref在注入Dao到Service中
DataSource --> JdbcTemplate --> Dao --> Service --> Action/Servlet
"-->"表示将左边的对象注入到右边的对象当中
准备数据库表
![8b9fe64d87d7671b69f78a98909e3325.png](https://img-blog.csdnimg.cn/img_convert/8b9fe64d87d7671b69f78a98909e3325.png)
创建User
![1ff0f2541961b3cd819d6cec06303b59.png](https://img-blog.csdnimg.cn/img_convert/1ff0f2541961b3cd819d6cec06303b59.png)
创建UserDao
public interface UserDao {
/**
* 查询总条数
*/
public Integer queryCount();
/**
* 添加
*/
public void addUser(User user);
/**
* 修改
*/
public void updateUser(User user);
/**
* 删除
*/
public void deleteUser(Integer id);
/**
* 查询一个
*/
public User queryUserById(Integer id);
/**
* 全查询
*/
public List<User> queryAllUserForList();
/**
* 全查询
*/
public List<Map<String,Object>> queryAllUserForMap();
}
创建UserDaoImpl
![731984cfc29cc61d8b312f9260ca2752.png](https://img-blog.csdnimg.cn/img_convert/731984cfc29cc61d8b312f9260ca2752.png)
创建UserService
和UserDao一样
创建UserServiceImpl
![3b445200d35a444de82ccc759edf1caa.png](https://img-blog.csdnimg.cn/img_convert/3b445200d35a444de82ccc759edf1caa.png)
创建UserAction
public class UserAction {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public Integer queryCount() {
return this.userService.queryCount();
}
public void addUser(User user) {
this.userService.addUser(user);
}
public void updateUser(User user) {
this.userService.updateUser(user);
}
public void deleteUser(Integer id) {
this.userService.deleteUser(id);
}
public User queryUserById(Integer id) {
return this.userService.queryUserById(id);
}
public List<User> queryAllUserForList() {
return this.userService.queryAllUserForList();
}
public List<Map<String, Object>> queryAllUserForMap() {
return this.userService.queryAllUserForMap();
}
}
创建db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=123456
创建applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 引入db.properties -->
<context:property-placeholder location="classpath:db.properties" system-properties-mode="FALLBACK"/>
<!-- 声明dataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 注入连接属性 -->
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 声明jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 声明dao -->
<bean id="userDao" class="com.sxt.dao.impl.UserDaoImpl">
<!-- 注入jdbcTemplate -->
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 声明service -->
<bean id="userService" class="com.sxt.service.impl.UserServiceImpl">
<!-- 注入dao -->
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 声明action -->
<bean id="userAction" class="com.sxt.action.UserAction">
<property name="userService" ref="userService"></property>
</bean>
</beans>
测试
![d0dccc13554e9632a5c86ece00ea68cf.png](https://img-blog.csdnimg.cn/img_convert/d0dccc13554e9632a5c86ece00ea68cf.png)
5、使用IOC和DI去完成上面的程序注解方式
修改UserAction
![b99d0e9a7d6e9425d7212a2d2cdc1117.png](https://img-blog.csdnimg.cn/img_convert/b99d0e9a7d6e9425d7212a2d2cdc1117.png)
修改UserServceImpl
![c5c81631619f573de8d3802428ce8271.png](https://img-blog.csdnimg.cn/img_convert/c5c81631619f573de8d3802428ce8271.png)
修改UserDaoImpl
![30218da7dfa3bab6f047bb860a52d84c.png](https://img-blog.csdnimg.cn/img_convert/30218da7dfa3bab6f047bb860a52d84c.png)
修改applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 引入db.properties -->
<context:property-placeholder location="classpath:db.properties" system-properties-mode="FALLBACK"/>
<!-- 声明dataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 注入连接属性 -->
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 声明jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<context:component-scan base-package="com.sxt.dao.impl"></context:component-scan>
<context:component-scan base-package="com.sxt.service.impl"></context:component-scan>
<context:component-scan base-package="com.sxt.action"></context:component-scan>
</beans>
6,JdbcTemplate的完成CURD
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Integer queryCount() {
return this.jdbcTemplate.queryForObject("select count(1) from user ", Integer.class);
}
@Override
public void addUser(User user) {
// this.jdbcTemplate.update("insert into user(name,age,email) values('小明',22,'23412342@qq.com')")
String sql="insert into user(name,age,email) values(?,?,?)";
Object [] objs= {user.getName(),user.getAge(),user.getEmail()};
this.jdbcTemplate.update(sql, objs);
}
@Override
public void updateUser(User user) {
String sql="update user set name=?,age=?,email=? where id=?";
Object [] objs= {user.getName(),user.getAge(),user.getEmail(),user.getId()};
this.jdbcTemplate.update(sql, objs);
}
@Override
public void deleteUser(Integer id) {
String sql="delete from user where id=?";
Object [] objs= {id};
this.jdbcTemplate.update(sql, objs);
}
@Override
public User queryUserById(Integer id) {
String sql="select * from user where id=?";
Object [] objs= {id};
// return this.jdbcTemplate.queryForObject(sql, objs, User.class); 只能处理返回数据是一行一列的数据
return this.jdbcTemplate.queryForObject(sql, objs, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
Integer userid=rs.getInt("id");
String name=rs.getString("name");
Integer age=rs.getInt("age");
String email=rs.getString("email");
User user=new User(userid, name, age, email);
return user;
}
});
}
@Override
public List<User> queryAllUserForList() {
String sql="select * from user";
// return this.jdbcTemplate.queryForList(sql, User.class);//只能查询多行一列的数据
return this.jdbcTemplate.query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
Integer userid=rs.getInt("id");
String name=rs.getString("name");
Integer age=rs.getInt("age");
String email=rs.getString("email");
User user=new User(userid, name, age, email);
return user;
}
});
}
@Override
public List<Map<String, Object>> queryAllUserForMap() {
String sql="select * from user";
return this.jdbcTemplate.queryForList(sql);
}
}
14【掌握】spring定时任务
1,定时任务概述
1、Quartz介绍
在企业应用中,我们经常会碰到时间任务调度的需求,比如每天凌晨生成前天报表,每小时生成一次汇总数据等等。Quartz是出了名的任务调度框架,它可以与J2SE和J2EE应用程序相结合,功能灰常强大,轻轻松松就能与Spring集成,使用方便。
2、Quartz中的概念
主要有三个核心概念:调度器、任务和触发器。三者关系简单来说就是,调度器负责调度各个任务,到了某个时刻或者过了一定时间,触发器触动了,特定任务便启动执行。概念相对应的类和接口有:
1)JobDetail:望文生义就是描述任务的相关情况;
2)Trigger:描述出发Job执行的时间触发规则。有SimpleTrigger和CronTrigger两个子类代表两种方式,一种是每隔多少分钟小时执行,则用SimpleTrigger;另一种是日历相关的重复时间间隔,如每天凌晨,每周星期一运行的话,通过Cron表达式便可定义出复杂的调度方案。
3)Scheduler:代表一个Quartz的独立运行容器,Trigger和JobDetail要注册到Scheduler中才会生效,也就是让调度器知道有哪些触发器和任务,才能进行按规则进行调度任务。
2,xml配置JobDteail通过MethodInvokeJobDetailFactoryBean实现【熟悉】
创建项目和导包
![6d47a6672b2a449bffaba7de5abf1e0b.png](https://img-blog.csdnimg.cn/img_convert/6d47a6672b2a449bffaba7de5abf1e0b.png)
创建MyJob
![40c7d6e3f576538b1d609c09dbdbaf13.png](https://img-blog.csdnimg.cn/img_convert/40c7d6e3f576538b1d609c09dbdbaf13.png)
创建application-task.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置Job类 -->
<bean id="myJob" class="com.sxt.task.MyJob"></bean>
<!-- 配置JobDetail 让定时任务知道要执行 myJob里面的哪一个方法-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 执行目标job -->
<property name="targetObject" ref="myJob"></property>
<!-- 要执行的方法 -->
<property name="targetMethod" value="execute"></property>
</bean>
<!-- 配置tirgger触发器 -->
<bean id="cronTriggerFactoryBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 注入 任务-->
<property name="jobDetail" ref="jobDetail"></property>
<!-- 注入时间规则 执行时间 每5秒执行一次 -->
<property name="cronExpression" value="0/5 * * * * ?"></property>
</bean>
<!-- 声明调度器 -->
<bean id="springJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<array>
<ref bean="cronTriggerFactoryBean"/>
</array>
</property>
</bean>
</beans>
创建applicationContext.xml
![8c31c39284e881d2b98735a8cf90e003.png](https://img-blog.csdnimg.cn/img_convert/8c31c39284e881d2b98735a8cf90e003.png)
测试
![c7698e0b171baa368830d63e63951d51.png](https://img-blog.csdnimg.cn/img_convert/c7698e0b171baa368830d63e63951d51.png)
![59500a60b7add329421a4a38cd335ffe.png](https://img-blog.csdnimg.cn/img_convert/59500a60b7add329421a4a38cd335ffe.png)
3,xml配置JobDteail通过JobDetailBean实现(推荐)
创建MyJobDteail
![257d3bc9ce1f2490f74493591b444e60.png](https://img-blog.csdnimg.cn/img_convert/257d3bc9ce1f2490f74493591b444e60.png)
创建application-task2.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置JobDetail 让定时任务知道要执行 myJob里面的哪一个方法-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<!-- 执行目标job的class地址 -->
<property name="jobClass" value="com.sxt.task.MyJobDteail" ></property>
<!-- 设置是否重复执行-->
<property name="durability" value="true"></property>
</bean>
<!-- 配置tirgger触发器 -->
<bean id="cronTriggerFactoryBean" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- 注入 任务-->
<property name="jobDetail" ref="jobDetail"></property>
<!-- 注入时间规则 执行时间 每5秒执行一次 -->
<property name="cronExpression" value="0/5 * * * * ?"></property>
</bean>
<!-- 声明调度器 -->
<bean id="springJobSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<array>
<ref bean="cronTriggerFactoryBean"/>
</array>
</property>
</bean>
</beans>
修改applicationContext.xml
![9597ff672a616ffe21c418bc9f2e73d0.png](https://img-blog.csdnimg.cn/img_convert/9597ff672a616ffe21c418bc9f2e73d0.png)
4,注解配置【掌握】最简单
创建myJob
![2d51db07202f355da303d96ef9ed44d9.png](https://img-blog.csdnimg.cn/img_convert/2d51db07202f355da303d96ef9ed44d9.png)
修改applicationContext.xml
s
![77cedc938e1b50edcac7611074992104.png](https://img-blog.csdnimg.cn/img_convert/77cedc938e1b50edcac7611074992104.png)
5,corn表达式
http://cron.qqe2.com/
![b203b00a7cb615fe47b47393c544d4dc.png](https://img-blog.csdnimg.cn/img_convert/b203b00a7cb615fe47b47393c544d4dc.png)
16【掌握】spring+mybatis集成
准备工作
创建项目
![6e3c98098dd8c7a07d1e284d111d01bc.png](https://img-blog.csdnimg.cn/img_convert/6e3c98098dd8c7a07d1e284d111d01bc.png)
导包
spring
![9149db490cdb0a4e1931edd0bc999997.png](https://img-blog.csdnimg.cn/img_convert/9149db490cdb0a4e1931edd0bc999997.png)
mybatis
|--核心包 mybatis.3.5.1.jar
![e85e5925134751df40cd09fef85f6a0a.png](https://img-blog.csdnimg.cn/img_convert/e85e5925134751df40cd09fef85f6a0a.png)
|--集成包 mybatis-spring.2.0.1.jar
![ba17433e2a6177d00efc34c2e5c78a7c.png](https://img-blog.csdnimg.cn/img_convert/ba17433e2a6177d00efc34c2e5c78a7c.png)
|--分页插件 pageHelper
![0e7a8d829ce880e921e55153dd0eda40.png](https://img-blog.csdnimg.cn/img_convert/0e7a8d829ce880e921e55153dd0eda40.png)
![8a67dbd7b14cde4748558b22578e7893.png](https://img-blog.csdnimg.cn/img_convert/8a67dbd7b14cde4748558b22578e7893.png)
mysql
![e0202dba8cf804ddc3723f8626b10f60.png](https://img-blog.csdnimg.cn/img_convert/e0202dba8cf804ddc3723f8626b10f60.png)
日志包
![ed5c9604dcd432579c06a5a537409710.png](https://img-blog.csdnimg.cn/img_convert/ed5c9604dcd432579c06a5a537409710.png)
![1fb26fcc43bcf90d6c8e41bffda64925.png](https://img-blog.csdnimg.cn/img_convert/1fb26fcc43bcf90d6c8e41bffda64925.png)
![285e45f43aedae2652a0d4a33659e625.png](https://img-blog.csdnimg.cn/img_convert/285e45f43aedae2652a0d4a33659e625.png)
连接池的包
DriverMangaerDataSource spring自带的
c3p0
dbcp
druid
创建log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
创建db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/test
username=root
password=123456
集成mybatis有mybatis.cfg.xml
生成User
![fbed010141c6de57adbe1f62310b52a9.png](https://img-blog.csdnimg.cn/img_convert/fbed010141c6de57adbe1f62310b52a9.png)
生成UserMapper
![1a0f2ae3a773f3c96db913cb0044f651.png](https://img-blog.csdnimg.cn/img_convert/1a0f2ae3a773f3c96db913cb0044f651.png)
生成UserMapper.xml
不修改
创建mybatis.cfg.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//http://mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置日志输出形式 -->
<settings>
<setting name="logImpl" value="LOG4J" />
</settings>
<!-- 配置别名 -->
<typeAliases>
<package name="com.sxt.domain"/>
</typeAliases>
<!-- 配置分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<!-- 加载mybait数据库操作的映射文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>
创建application-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 引入db.properties -->
<context:property-placeholder location="classpath:db.properties" system-properties-mode="FALLBACK"/>
<!-- 声明dataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 注入连接属性 -->
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 声明sessionFactory 并注入mybatis.cfg.xml-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入mybatis.cfg.xml -->
<property name="configLocation" value="classpath:mybatis.cfg.xml"></property>
<!-- 注入数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 扫描mapper接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入mapper接口所在的包 -->
<property name="basePackage" value="com.sxt.mapper"></property>
<!-- 注入sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
</beans>
创建application-service.xml
![dde9c8fc1a1f76b38e6da8ebba34441c.png](https://img-blog.csdnimg.cn/img_convert/dde9c8fc1a1f76b38e6da8ebba34441c.png)
创建applicationContext.xml
![eaee08277800e4a714dfa466984f6cad.png](https://img-blog.csdnimg.cn/img_convert/eaee08277800e4a714dfa466984f6cad.png)
创建UserService
![957a61d7863bdba7d51fd52bfb616848.png](https://img-blog.csdnimg.cn/img_convert/957a61d7863bdba7d51fd52bfb616848.png)
创建UserServiceImpl
![47c9b6f5d52ceba2c04be73b8ffb4dee.png](https://img-blog.csdnimg.cn/img_convert/47c9b6f5d52ceba2c04be73b8ffb4dee.png)
测试
![e6141aa35e65ed34b459bc17060aeab8.png](https://img-blog.csdnimg.cn/img_convert/e6141aa35e65ed34b459bc17060aeab8.png)
集成mybatis无mybatis.cfg.xml
删除mybatis.cfg,xml
修改application-dao.xml
![b355cf9de2be255020143347a3a13170.png](https://img-blog.csdnimg.cn/img_convert/b355cf9de2be255020143347a3a13170.png)
17【掌握】声明式事务AOP
注解配置
修改UserServiceImpl
![e8e0f35afc1f039710625e85aec68887.png](https://img-blog.csdnimg.cn/img_convert/e8e0f35afc1f039710625e85aec68887.png)
修改applicatin-service.xml
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启动注解事务 -->
<tx:annotation-driven/>
XML的配置
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:component-scan base-package="com.sxt.service.impl"></context:component-scan>
<!-- 1,声明事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启动注解事务 -->
<!-- <tx:annotation-driven/> -->
<!-- 2,声明事务的传播特性 也就是通知 -->
<tx:advice id="advise" transaction-manager="transactionManager">
<tx:attributes>
<!-- 以add开头的方法名需要事务 -->
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="change*" propagation="REQUIRED"/>
<tx:method name="reset*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="load*" read-only="true"/>
<tx:method name="*" read-only="true"/>
<!-- 相关属性说明
声明事务切面 告诉spring框架,将哪些方法放入到事务中,以及事务特征
propagation:
REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类 似的操作
read-only="true",只读事务,对数据库只能是查询操作
-->
</tx:attributes>
</tx:advice>
<!-- 3进行AOP织入 -->
<aop:config>
<!-- 声明切面 -->
<aop:pointcut expression="execution(* com.sxt.service.impl.*.*(..))" id="pc1"/>
<!-- 织入 -->
<aop:advisor advice-ref="advise" pointcut-ref="pc1"/>
</aop:config>
</beans>