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开头的方法

execution(* com.xyz.service.AccountService.*(..))                              AccountService类中的所有方法

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框架的第二种核心掌握)的更多相关文章

  1. Spring官方文档翻译——15.1 介绍Spring Web MVC框架

    Part V. The Web 文档的这一部分介绍了Spring框架对展现层的支持(尤其是基于web的展现层) Spring拥有自己的web框架--Spring Web MVC.在前两章中会有介绍. ...

  2. 是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。

    看了 Pivotal 公司的发展历史,这尼玛就是一场商业大片呀. 我们刚开始学习 Spring Boot 的时候肯定都会看到这么一句话: Spring Boot 是由 Pivotal 团队提供的全新框 ...

  3. 【转帖】是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了。

    是时候给大家介绍 Spring Boot/Cloud 背后豪华的研发团队了. 2019/01/03 http://www.ityouknow.com/springboot/2019/01/03/spr ...

  4. Spring入门篇——第7章 Spring对AspectJ的支持

    第7章 Spring对AspectJ的支持 介绍Spring对AspectJ的支持 7-1 AspectJ介绍及Pointcut注解应用 实例 完成了在xml文件的配置 7-2 Advice定义及实例 ...

  5. 带你手写基于 Spring 的可插拔式 RPC 框架(一)介绍

    概述 首先这篇文章是要带大家来实现一个框架,听到框架大家可能会觉得非常高大上,其实这和我们平时写业务员代码没什么区别,但是框架是要给别人使用的,所以我们要换位思考,怎么才能让别人用着舒服,怎么样才能让 ...

  6. 关于如何介绍spring框架。

    一.介绍Spring 1.Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架. 2.概念:轻量级的IOC(控制反转或者依赖注入).AOP(面向切面或者面向方面) ...

  7. Spring框架学习03——Spring Bean 的详解

    1.Bean 的配置 Spring可以看做一个大型工厂,用于生产和管理Spring容器中的Bean,Spring框架支持XML和Properties两种格式的配置文件,在实际开发中常用XML格式的配置 ...

  8. Spring4- 01 - Spring框架简介及官方压缩包目录介绍- Spring IoC 的概念 - Spring hello world环境搭建

    一. Spring 框架简介及官方压缩包目录介绍 主要发明者:Rod Johnson 轮子理论推崇者: 2.1 轮子理论:不用重复发明轮子. 2.2 IT 行业:直接使用写好的代码. Spring 框 ...

  9. Spring框架IOC和AOP介绍

    说明:本文部分内容参考其他优秀博客后结合自己实战例子改编如下 Spring框架是个轻量级的Java EE框架.所谓轻量级,是指不依赖于容器就能运行的.Struts.Hibernate也是轻量级的. 轻 ...

随机推荐

  1. postgresql如何维护WAL日志/归档日志

    WAL日志介绍 wal全称是write ahead log,是postgresql中的online redo log,是为了保证数据库中数据的一致性和事务的完整性.而在PostgreSQL 7中引入的 ...

  2. C++中4个类型转换相关的关键字/特点/应用场合

    reinterpret_cast是C++里面的一个强制类型转换符,能够将任何的指针类型转换成其他的任何指针类型:能够将任何的整数类型转换成指针类型,反之亦然:滥用reinterpret_cast强制类 ...

  3. Vuejs 页面的区域化与组件封装

    组件的好处 当我用vue写页面的时候,大量的数据页面渲染,引入组件简化主页面的代码量,当代码区域块代码差不多相同时,组件封装会更加简化代码.组件是Vue.js最强大的功能之一. 组件可以扩展HTML元 ...

  4. ActiveMQ笔记——技术点汇总

    目录 · Introduction to ActiveMQ · Installing ActiveMQ · Message-oriented middleware · JMS specificatio ...

  5. 怎么调用api接口

    api的简单调用,调用api的方法 方法一:用前端方法调用api 完整代码: <!DOCTYPE html> <html lang="en"> <he ...

  6. Domain Driven Design

    在Spring官网的第一个tutorial中看到了这种 设计模式 Domain Driven Design 找到了篇介绍这个得文章: What is Domain Driven Design? &qu ...

  7. Java 关于路径

    在eclipse中如果没有指名文件的路径的话,系统默认是与src同一级别的目录路径!

  8. KVM虚拟化主机安装

    KVM虚拟化主机安装 最小化安装CentOS6.X或者CentOS7.X,RHEL6.X以上系列建议建议选择安装最小虚拟化主机 如果要安装桌面可以先选择最小化虚拟主机,再选择Gnome桌面包 安装过程 ...

  9. win8下安装VC6出现兼容性问题的解决办法

    重装系统之后(win8的系统),发现VC6安装出现兼容性问题,花了一些时间解决,有出现的问题都差不多在下面链接的总结中,写的很详细: http://www.docin.com/p-1126120829 ...

  10. 201521123042 《java程序设计》 第八周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. ①泛型定义:泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展, ...