spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)
1、Spring的AOP编程
什么是AOP? ----- 在软件行业AOP为Aspect Oriented Programming 也就是面向切面编程,使用AOP编程的好处就是:在不修改源代码的情况下,可以实现代码功能的增强
AOP的实现原理(掌握)
JDK的动态代理(注意JDK的动态代理只能对实现了接口的类产生代理)
/**
* Jdk的动态代理
* @author lilong
*/
public class JdkProxy implements InvocationHandler{
//要代理的对象
private CustomerDao customerDao;
public JdkProxy(CustomerDao customerDao){
this.customerDao = customerDao;
}
/**
* 生成代理对象的方法
* @return
*/
public CustomerDao createProxy(){
CustomerDao proxy = (CustomerDao) Proxy.newProxyInstance(customerDao.getClass().getClassLoader(), customerDao.getClass().getInterfaces(), this);
return proxy;
}
/**
* 增强的方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限校验...");
return method.invoke(customerDao, args);
}
}
编写测试代码:
@Test
public void test1(){
CustomerDao customerDao = new CustomerDaoImpl();
JdkProxy jdkProxy = new JdkProxy(customerDao);
CustomerDao proxy = jdkProxy.createProxy();
proxy.save();
}
第二种代理方式Cglib方式(了解或者欣赏)
注意的是:Cglib可以对没有实现接口的类产生代理,生成子类来实现功能的增强
public class CglibProxy implements MethodInterceptor{
//要代理的对象
private LinkManDao linkManDao;
public CglibProxy(LinkManDao linkManDao) {
this.linkManDao = linkManDao;
}
public LinkManDao createProxy(){
//创建Cglib核心类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(linkManDao.getClass());
//设置回调
enhancer.setCallback(this);
//生成代理
LinkManDao proxy = (LinkManDao) enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("日志记录");
Object obj = methodProxy.invokeSuper(proxy, args);
return obj;
}
}
n 编写测试代码
@Test
public void test2(){
LinkManDao linkManDao = new LinkManDao();
CglibProxy cglibProxy = new CglibProxy(linkManDao);
LinkManDao proxy = cglibProxy.createProxy();
proxy.save();
}
2、Spring的AOP开发方式(xml方式)
其中相关术语的介绍

AOP开发所需要的jar介绍
n AOP联盟的jar包:com.springsource.org.aopalliance-1.0.0.jar
n Spring提供的AOP的jar包:spring-aop-4.2.4.RELEASE.jar
n AspectJ的jar包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
n Spring整合AspectJ的jar包:spring-aspects-4.2.4.RELEASE.jar

编写接口和实现类
ProductDao接口:
public interface ProductDao {
/**
* 持久层:产品保存
*/
public void save();
}
ProductDaoImpl实现类:
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
}
配置相关类到Spring中
<?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"
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">
<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>
</beans>
编写切面类
/**
* 自定义切面类
* @author kevin
*/
public class MyAspectXml {
public void checkPrivilege(){
System.out.println("权限校验...");
}
}
配置切面类
<?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"
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">
<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>
<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>
</beans>
进行AOP配置
<?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">
<bean id="productDao" class="cn.itcast.dao.impl.ProductDaoImpl"></bean>
<bean id="myAspectXml" class="cn.itcast.aspect.MyAspectXml"></bean>
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
</beans>
编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAOP {
@Autowired
private ProductDao productDao;
@Test
public void test1(){
productDao.save();
}
}
总结:对切入点表达式语法进行总结
语法:[修饰符] 返回类型 包名.类名.方法名(形式参数)
常见写法:
n execution(public * *(..)) 所有的public方法
n execution(* set(..)) 所有set开头的方法
n execution(* com.xyz.service.AccountService.*(..)) AccountService类中的所有方法
n execution(* com.xyz.service.*.*(..)) com.xyz.service包下所有的方法
n execution(* com.xyz.service..*.*(..)) com.xyz.service包及其子包下所有的方法
3、Spring中AOP的通知类型
1.1.1. 前置通知:在方法执行之前增强。可以获得切入点信息。
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
}
1.1.2. 后置通知:在方法执行完之后增强。可以获取返回值信息。
/**
* 自定义切面类
* @author kevin
*/
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
}
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
</aop:aspect>
</aop:config>
1.1.3. 环绕通知:在方法执行前后都进行增强。可以阻止方法的执行。
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
@Override
public void update() {
System.out.println("持久层:产品更新");
}
}
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
public Object around(ProceedingJoinPoint joinpoint){
System.out.println("环绕前执行");
Object obj = null;
try {
obj = joinpoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后执行");
return obj;
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
</aop:aspect>
</aop:config>
1.1.4. 异常抛出通知:当发生异常之后增强,可以获取异常信息。
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
@Override
public void update() {
System.out.println("持久层:产品更新");
}
@Override
public void find() {
System.out.println("持久层:查询");
int i = 10/0;
}
}
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
public Object around(ProceedingJoinPoint joinpoint){
System.out.println("环绕前执行");
Object obj = null;
try {
obj = joinpoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后执行");
return obj;
}
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知:" + ex.getMessage());
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!-- 抛出异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
</aop:aspect>
</aop:config>
1.1.5. 最终通知:不管是否有异常,都会执行的
public class MyAspectXml {
public void checkPrivilege(JoinPoint point){
System.out.println("权限校验..." + point);
}
public void afterReturn(Object result){
System.out.println("后置通知:" + result);
}
public Object around(ProceedingJoinPoint joinpoint){
System.out.println("环绕前执行");
Object obj = null;
try {
obj = joinpoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("环绕后执行");
return obj;
}
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知:" + ex.getMessage());
}
public void after(){
System.out.println("最终通知");
}
}
<!-- AOP配置 -->
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))" id="pointcut4"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspectXml">
<!-- 前置通知 -->
<aop:before method="checkPrivilege" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="afterReturn" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!-- 抛出异常通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="pointcut4"/>
</aop:aspect>
</aop:config>
注意:最终通知和后置通知的区别:最终通知,不管异常与否,都执行;而后置通知在异常时不执行。
4、Spring的AOP注解
4.1. 创建工程,引入jar包,创建核心配置文件

<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="cn.itcast"></context:component-scan>
<!-- 开启自动代理注解 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
4.2. 创建接口和实现类
public interface ProductDao {
/**
* 持久层:产品保存
*/
public void save();
public int delete();
public void update();
public void find();
}
@Repository("productDao")
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("持久层:产品保存...");
}
public int delete(){
System.out.println("持久层:产品删除...");
return 100;
}
@Override
public void update() {
System.out.println("持久层:产品更新");
}
@Override
public void find() {
System.out.println("持久层:查询");
}
}
4.3. 编写切面类
@Component("myAspectAnnotation")
@Aspect
public class MyAspect {
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
}
提示:此处的切面类可以不取id.
5、Spring的AOP 中注解通知
5.1. 前置通知
/**
* 前置通知
* @param joinPoint
*/
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
5.2. 后置通知
@Aspect
public class MyAspect {
/**
* 前置通知
* @param joinPoint
*/
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")
public void afterReturning(Object result){
System.out.println("后置通知:" + result);
}
}
5.3. 环绕通知
@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")
public Object after(ProceedingJoinPoint joinpoint) throws Throwable{
System.out.println("环绕通知前增强");
Object obj = joinpoint.proceed();
System.out.println("环绕通知后增强");
return obj;
}
5.4. 异常通知
@AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知");
}
5.5. 最终通知
@After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")
public void after(){
System.out.println("最终通知");
}
5.6. PointCut注解(了解)
作用:用于定义切入点表达式的一个注解。
@Component("myAspectAnnotation")
@Aspect
public class MyAspect {
/**
* 前置通知
* @param joinPoint
*/
@Before("execution(* cn.itcast.dao.impl.ProductDaoImpl.save(..))")
public void checkPrivilege(JoinPoint joinPoint){
System.out.println("权限校验..." + joinPoint.toString());
}
@AfterReturning(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.delete(..))",returning="result")
public void afterReturning(Object result){
System.out.println("后置通知:" + result);
}
@Around("execution(* cn.itcast.dao.impl.ProductDaoImpl.update(..))")
public Object aroung(ProceedingJoinPoint joinpoint) throws Throwable{
System.out.println("环绕通知前增强");
Object obj = joinpoint.proceed();
System.out.println("环绕通知后增强");
return obj;
}
// @AfterThrowing(value="execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))",throwing="ex")
@AfterThrowing(value="MyAspect.pointcut()",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println("抛出异常通知");
}
// @After("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")
@After("MyAspect.pointcut()")
public void after(){
System.out.println("最终通知");
}
@Pointcut("execution(* cn.itcast.dao.impl.ProductDaoImpl.find(..))")
public void pointcut(){
}
}
spring框架总结(03)重点介绍(Spring框架的第二种核心掌握)的更多相关文章
- Spring官方文档翻译——15.1 介绍Spring Web MVC框架
Part V. The Web 文档的这一部分介绍了Spring框架对展现层的支持(尤其是基于web的展现层) Spring拥有自己的web框架--Spring Web MVC.在前两章中会有介绍. ...
- 是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。
看了 Pivotal 公司的发展历史,这尼玛就是一场商业大片呀. 我们刚开始学习 Spring Boot 的时候肯定都会看到这么一句话: Spring Boot 是由 Pivotal 团队提供的全新框 ...
- 【转帖】是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。
是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了. 2019/01/03 http://www.ityouknow.com/springboot/2019/01/03/spr ...
- Spring入门篇——第7章 Spring对AspectJ的支持
第7章 Spring对AspectJ的支持 介绍Spring对AspectJ的支持 7-1 AspectJ介绍及Pointcut注解应用 实例 完成了在xml文件的配置 7-2 Advice定义及实例 ...
- 带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍
概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让 ...
- 关于如何介绍spring框架。
一.介绍Spring 1.Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架. 2.概念:轻量级的IOC(控制反转或者依赖注入).AOP(面向切面或者面向方面) ...
- Spring框架学习03——Spring Bean 的详解
1.Bean 的配置 Spring可以看做一个大型工厂,用于生产和管理Spring容器中的Bean,Spring框架支持XML和Properties两种格式的配置文件,在实际开发中常用XML格式的配置 ...
- Spring4- 01 - Spring框架简介及官方压缩包目录介绍- Spring IoC 的概念 - Spring hello world环境搭建
一. Spring 框架简介及官方压缩包目录介绍 主要发明者:Rod Johnson 轮子理论推崇者: 2.1 轮子理论:不用重复发明轮子. 2.2 IT 行业:直接使用写好的代码. Spring 框 ...
- Spring框架IOC和AOP介绍
说明:本文部分内容参考其他优秀博客后结合自己实战例子改编如下 Spring框架是个轻量级的Java EE框架.所谓轻量级,是指不依赖于容器就能运行的.Struts.Hibernate也是轻量级的. 轻 ...
随机推荐
- Web.py 框架学习笔记 - URL处理
最近由于工作需要开始学习基于python的web应用框架web.py.为了方便学习,将学习心得逐日记下以便日后复习. URL 模板: web.py提供了一套url处理的模板,在python工程中,只需 ...
- LVS之-LAMP搭建wordpress
author:JevonWei 版权声明:原创作品 LVS搭建wordpress,涉及的知识点有DNS,LAMP,NFS及LVS 网络拓扑图 网络环境 NFS 192.168.198.130 mysq ...
- chrome开发工具指南(二)
Application 面板 使用 App Manifest 窗格检查您的网络应用清单和触发 Add to Homescreen 事件. 使用 Service Worker 窗格执行与服务工作线程相关 ...
- 关于javascript原型链的个人理解
首先js是一种面对对象的语言,虽然大多数时候是以面对过程的形式展现出来.先来看一段代码: function Base() { this.name = 'tarol'; } function Sub() ...
- 团队作业8——第二次项目冲刺(Beta阶段)5.22
1.当天站立式会议照片 会议内容: ①:检查总结上次任务完成情况 ②:安排本次任务的分工 ③:反思前三次自己的不足 ④:协商解决代码进度.成员投入时间等问题 2.每个人的工作 工作中遇到的困难: 代码 ...
- JAVA基础第一组(前5道题)
1.[程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一 对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔 ...
- Core Java 简单谈谈HashSet
同学们在看这个问题的时候,我先提出者两个问题,然后大家带着问题看这个文章会理解的更好. HashSet为什么添加元素时不能添加重复元素? HashSet是否添加null元素? 打开源码, 我们看到如下 ...
- Spring Boot Maven Plugin(二):run目标
简介 Spring Boot Maven Plugin插件提供spring boot在maven中的支持.允许你打包可运行的jar包或war包. 插件提供了几个maven目标和Spring Boot ...
- 纳税服务系统【用户模块之使用POI导入excel、导出excel】
前言 再次回到我们的用户模块上,我们发现还有两个功能没有完成: 对于将网页中的数据导入或导出到excel文件中,我们是完全没有学习过的.但是呢,在Java中操作excel是相对常用的,因此也有组件供我 ...
- sourcetree和gitlab配置图解
一.前期准备安装 1.git客户端(1.产生gitlab服务端和本地git相互传输时所需要校验的私钥和公钥 2.直接在Idea中使用git提交和push代码,当然也可以用sourcetree提交 ...