Spring 框架第二天 AOP切面编程

今天重点内容:

1、 什么是AOP ? AOP实现原理是怎样的? AOP相关术语

2、 AOP底层实现 (了解) ----- JDK动态代理、 Cglib动态代理

3、 传统Spring AOP 编程 (了解实现,掌握使用 )

4、 基于AspectJ 框架,实现spring2.0之后 AOP 编程(重点)

5、 Spring JdbcTemplate 模板工具类 使用 (ORM 解决方案 )--- 类似Apache DbUtils

1.  AOP面向切面编程概述

1.1.  什么是AOP ?

l AOP Aspect Oriented Programing 面向切面编程

1) 一种程序设计思想

2)

3) AOP是OOP (Object Oriented Programing )延伸

l 思想:AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视、事务管理、安全检查、缓存)

AOP底层就是代理的增强 !

l 面试题:在项目哪些功能使用AOP ? --- AOP使用场景

1、性能监视 (方法运行时间)

2、事务管理

3、安全检查 (权限 )

4、缓存优化 (第一次访问,查询数据,放入缓存, 第二次以后访问 从缓存返回 )

5、记录日志

l 学习AOP 分为两个部分

1、 学习传统Spring AOP编程 (Spring1.2年代 )

2、 学习AspectJ 框架的AOP编程 (Spring2.0以后年代 )

1.2.  AOP开发术语

切面由切入点和通知组成!

2.  AOP的底层实现(了解)

2.1.  JDK 动态代理机制

1、必须针对接口进行代理

2、生成代理对象,通过Proxy类

进行代理 ,传入目标对象类加载器、 目标对象接口 、 处理类

3、自己实现InvocationHandler 接口

对目标对象方法调用时,都会执行invoke方法,起到拦截作用

第一步: 编写业务接口和实现类

第二步: 编写传统调用,编写基于代理调用

// 生成代理工具类

public class JdkProxyFactory implements InvocationHandler{

// 目标对象

private Object target;

public JdkProxyFactory(Object target) {

this.target = target;

}

// 创建代理对象

public Object createJdkProxy(){

return Proxy.newProxyInstance(

target.getClass().getClassLoader(),

target.getClass().getInterfaces(),

this);

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// 记录日志

System.out.println("日志记录:" + method.getName() + "执行了...");

return method.invoke(target, args);

}

}

第三步: 测试代码

2.2.  Cglib动态代理机制

JDK只能对接口进行代理,如果目标对象没有接口,无法使用JDK动态代理 ---- 使用cglib

什么是cglib ?

CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。

Cglib可以对接口或者类进行代理 !

使用Spring最新版本开发,无需单独下载cglib (spring core 已经集成cglib )

Cglib开发依赖 asm的jar (spring core 已经集成 asm )

1、 编写目标业务类

2、编写Cglib 生成代理工厂类

// 生成cglib代理工厂

public class CglibProxyFactory implements MethodInterceptor {

// 目标对象

private Object target;

public CglibProxyFactory(Object target) {

this.target = target;

}

// 生成代理对象方法

public Object createCglibProxy() {

// 通过Enhancer 生成代理

Enhancer enhancer = new Enhancer();

// 设置超类

// 生成UserDAO的子类

enhancer.setSuperclass(target.getClass());

// 设置回调处理类

enhancer.setCallback(this);

// 生成代理返回

return enhancer.create();

}

@Override

/**

* proxy 代理对象

* method 方法反射对象

* args 参数

* methodProxy 方法的代理对象,用于执行父类的方法

*/

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

System.out.println("cglib 日志: 调用了" + method.getName() + "方法...");

// return method.invoke(target, args);

return methodProxy.invokeSuper(proxy, args);// 调用真实对象方法

}

}

3、编写测试类

小结:

Spring AOP 就是基于JDKProxy 和 CglibProxy

1、如果目标对象有接口,优先使用JDK Proxy

2、如果目标对象没有接口, 使用CglibProxy

3.  传统Spring AOP 切面编程

传统 : Spring1.2 开始支持AOP编程 (这种编程,现在自己写的很少,但是我们会用到 )

Spring AOP编程,必须学习切入点和通知

1) 切入点,通过配置完成的

2) 通知,通过编程完成的

3.1.  传统AOP编程,通知类型(5种)

不同Advice 执行增强代码的时间点不同 !

3.2.  编写一个Advice

1、 导入jar包

传统Spring AOP开发

  • com.springsource.org.aopalliance-1.0.0.jar AOP联盟定义接口规范
  • spring-aop-3.2.0.RELEASE.jar Spring对AOP扩展支持

整合AspectJ AOP开发

  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar 第三方AspectJ 包
  • spring-aspects-3.2.0.RELEASE.jar Spring 对AspectJ 扩展支持

2、 编写Advice 实现 MethodInterceptor 环绕增强

3.3.  AspectJ 切入点语法

为什么要学习AspectJ切入点语法?

传统AOP切入点 ,使用正则表达式语法,现在基本上不去用

Spring没有支持所有AspectJ语法,所以我们学习Spring AOP 只能spring文档 !

AspectJ切入点,是通过函数进行配置

l execution 执行

n 语法:execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

execution(* *(..))  第一个* 任意返回类型 , 第二个* 任意方法名 , .. 任意参数

execution(* cn.itcast.service.UserService.*(..)) 匹配UserService所有方法

execution(* cn.itcast.service.UserService+.*(..)) 匹配UserService子类所有方法

execution(* cn.itcast.service..*.*(..)) 第一个.. 任意子包 *.*任何类的任何方法

l within 根据包匹配

n 语法:within(包名..*)

within(cn.itcast.service..*) 拦截service下所有类的方法

l this根据目标类型匹配

n 语法:this(类名)

this(cn.itcast.service.UserService) 拦截 UserService所有方法 (包括代理对象)

l target 根据目标类型匹配

n 语法 :target(类名)

target(cn.itcast.service.UserService) 拦截UserService所有方法 (不包括代理对象 )

l args 根据参数匹配

args(java.lang.String) 拦截所有参数为String类的方法

l bean 根据bean name匹配

bean(userService) 拦截bean id/name为userService对象所有方法

3.4.  配置传统Spring AOP切面

1、 引入aop的命名空间

<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"

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">

<!-- bean definitions here -->

</beans>

2、 配置切面

3、编写测试

图解:

注意: 需要对有接口实现类直接代理,不对接口代理 !

4.  AspectJ AOP切面编程(XML配置)

Spring1.2 开始支持AOP编程,主要代理对象创建通过ProxyFactoryBean构造 !

后来人们发现spring1.2 AOP开发太麻烦了,spring2.0 引入对AspectJ(第三方AOP框架)支持,AOP开发就被简化了。

4.1.  AspectJ支持通知类型 (6种)

相比传统AOP编程,多了一个After通知(最终通知, 效果finally )

4.2.  Before前置通知使用

分析前置通知应用场景: 权限控制、 记录访问日志

第一步: 编写Advice

第二步: 配置切入点和切面

面试题: advisor和 aspect的区别 ?

Advisor是传统Spring AOP 切面,只能有一个通知和一个切入点

Aspect 是AspectJ 提供切面,可以包括多个通知和多个切入点

面试题: aspect和aspectJ区别 ?

aspect 切面, 由切入点和通知组成

aspectJ 框架,进行AOP开发

===================== 扩展 struts2 拦截器机制是AOP思想吗?

1、 访问Action 进行代理 ActionProxy

2、 提供Interceptor 类似Advice 增强 ,通过配置使不同Action访问前执行不同拦截器

4.3.  AfterReturing 后置通知使用

在目标类的方法运行之后,进行代码增强

特性:操作目标方法返回值 

使用AspectJ 框架开发,可以将多个增强的方法,写在同一个类里面 !

第一步: 编写增强方法

第二步: 配置applicationContext.xml

4.4.  Around 环绕通知使用

在目标类方法 执行前和执行后,都可以增强

场景: 1) 运行方法时间监控 2) 事务管理 3) 权限控制 4) 缓存 5) 日志

第一步: 编写Advice增强方法

第二步: 配置切入点和切面

4.5.  AfterThrowing 抛出通知使用

在目标发生异常时,执行增强代码

场景: 目标方法异常,日志记录异常,将异常信息发送邮件给管理员

第一步: 编写抛出增强方法

第二步: 配置切入点和切面

当发生异常时, 目标方法后置通知不会执行的!!

4.6.  After最终通知使用

无论目标方法是否出现异常,都将执行增强代码

场景: 释放资源

try {

开启事务…

执行代码

} catch {

事务回滚

} finally {

事务提交

}

第一步: 编写增强方法

第二步: 配置切入点和切面

小结: Around环绕通知什么都可以

try{

前置通知…

执行目标方法

后置通知…

}catch {

异常通知…

}finally {

最终通知…

}

5.  AspectJ AOP 切面编程 (注解配置 )

新建 spring3_day3_annotation web 项目, 导入spring AOP开发jar包

5.1.  编写目标业务类

配置applicationContext.xml bean的扫描

5.2.  编写Advice增强

配置applicationContext.xml

使用注解修饰Advice类

@Aspect 这是一个切面

@Before 前置通知

@AfterReturning 后置通知

@Around 环绕通知

@AfterThrowing 抛出通知

@After最终通知

@Pointcut 切入点

小结:

1、 注册Bean  <context:component-scan> (@Service、@Controller、 @Repository 、@Component )

2、 声明具有增强方法类是一个切面 @Aspect

3、 在对应方法上,声明各种通知 @Before @AfterReturning @Around @AfterThrowing @After

4、 根据切面注解自动生成代理 <aop:aspectj-autoproxy  />

5.3.  使用@Pointcut 定义切入点

将公共切入点表达式,抽取出来,便于后期维护

Spring规定,将@Pointcut注解加到 私有、无返回值、无参数的方法上 (该方法的名字 就是切入点的名字 !)

如果引用切入点,类似方法调用

能否在一个通知上, 应用多个切入点 可以 && 或者 || 引入多个

pointcut1() && pointcut2() , 必须同时满足 pointcut1和pointcut2 切入点表达式

pointcut1()||pointcut2() 只需要满足 pointcut1 或者 pointcut2 当中一个切入点表达式

6.  Spring JdbcTemplate

学习spring 重点三--- 六章

第三章:核心技术: IoC和AOP

第四章:数据访问: (JDBC数据访问 JdbcTemplate 、 事务管理 、 整合ORM框架 )

第五章:Web应用 :SpringMVC --- 后续课程

第六章:整合

6.1.  JdbcTemplate 快速入门

JdbcTemplate 用来简化JDBC 编程开发,使用效果类似 DbUtils 框架

第一步: 新建web项目 spring3_day2_jdbctemplate ,导入jar包

4个核心

2个日志

1个web集成

1个junit集成

1个inject

4个AOP

导入 jdbc和tx 2个jar包

导入 oracle驱动

第二步: 编写无配置文件Jdbc程序

-- Create the user

create user SH1026

identified by ""

default tablespace SYSTEM

temporary tablespace TEMP

profile DEFAULT;

-- Grant/Revoke role privileges

grant connect to SH1026;

grant resource to SH1026;

-- Grant/Revoke system privileges

grant unlimited tablespace to SH1026;

6.2.  使用spring配置管理JdbcTemplate

在applicationContext.xml 配置数据库连接池和JdbcTemplate

6.2.1.  DrvierManagerDataSource 配置

测试

6.2.2.  DBCP 连接池BasicDataSource 配置

导入 dbcp 和pool的jar包

配置

6.2.3.  C3P0连接池 CombopooledDataSource 使用

导入c3p0的jar包

配置

6.2.4.  JNDI数据库配置使用

什么是JNDI ?

JNDI(Java Naming and Directory Interface,Java命名和目录接口)

在JNDI容器进行配置,将对象交给容器创建和管理,为对象进行命名 ,在JNDI容器其它程序通过名字去访问这个对象。

第一步: 在tomcat配置数据库连接池

需要在<Context>元素下配置 <Resouce> 元素

配置位置 : server.xml 、context.xml (所有项目生效)、 项目目录 WebRoot/META-INF (只对当前项目有效 )

在项目WebRoot/META-INF 新建context.xml

将数据库驱动包,复制tomcat/lib下

第二步: spring访问 配置JNDI

配置applicationContext.xml

编写Servlet ,从Spring获取对象

6.3.  外部属性文件的配置使用

什么是外部属性文件?

属性文件 --- properties文件

XML中很多内容,格式比properties 复杂, 将经常需要改动属性数据,配置properties文件, 便于后期维护!

在applicationContext.xml 引入属性文件,通过${} 引入属性值

6.4.  编写DAO程序,实现数据表CRUD操作

6.4.1.  建立数据表,编写实体类

建立customers数据表

-- Create table

create table customers

(

id   number,

name varchar2(50),

city varchar2(100),

age  number

)

;

-- Create/Recreate primary, unique and foreign key constraints

alter table customers

add constraint customers_pk primary key (ID);

实体类

6.4.2.  在DAO中注入JdbcTemplate

配置

6.4.3.  通过update方法,实现增加、修改、删除

JdbcTemplate提供

6.4.4.  通过queryXxx方法实现查询

l 返回简单类型数据

返回int : queryForInt

返回long: queryForLong

返回String : queryForObject(sql, requiredType, args ) requiredType就是返回类型

l 返回复杂类型数据:

需要使用RowMapper对象

什么是RowMapper ?  将每行数据封装为Customer对象

问题: 如果表中列非常多, 自定义RowMapper 非常复杂

类属性名和表列名,代码能否优化 !

Spring JdbcTemplate 提供ParameterizedBeanPropertyRowMapper ,自动完成同名列和属性 自动对应封装 !

今天总结:

1、 IoC和DI的概念和区别? IoC是如何实现的 ?

2、 什么AOP? 如何实现的? 在项目哪些功能中使用到AOP ?

3、 BeanFactory和FactoryBean的区别 ?

4、 singleton和prototype的区别 ? 能否写出单例设计模式代码实现 ?

5、 BeanPostProcessor 后处理的作用 ?

6、 如何用xml和注解 定义Bean? 如何完成属性注入 ?

7、 Spring AOP 使用什么技术实现的 ? 底层技术 JDK和Cglib动态代理

8、 传统Spring AOP 开发和配置

9、 重点掌握 AspectJ AOP 开发和配置 (XML和注解,重点掌握一种 )

10、 advisor、advice、aspect 区别

11、 SpringAOP 应用: 运行时间、 权限控制、 缓存、事务管理  …

12、 数据源配置 JNDI 和 C3p0 重点

SpringTest2的更多相关文章

  1. Spring的事务管理

    事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...

  2. AOP详解

    什么是AOP AOP Aspect Oriented Programing 面向切面编程 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.事务管理.安全检查.缓存) Spring ...

  3. Spring 学习总结 使用静态工厂创建Bean

    创建Bean时,class属性必须指定,此时为静态工厂类. factory-method指定静态工厂方法名. 接口: public interface Being { public void test ...

  4. (spring-第7回【IoC基础篇】)BeanDefinition的载入与解析&&spring.schemas、spring.handlers的使用

    报错信息:Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http: ...

  5. Spring中的BeanUtils与apache commons中的BeanUtils用法[1]

    1. 前言 在开发过程中,经常遇到把要给一个bean的属性赋给另外一个bean.最笨的方法是每个属性都单独写一个,聪明的方法是应用反射写一个工具方法.考虑到这个需求基本每个程序员都会遇到,那么一定已经 ...

  6. spring的配置模式与注解模式基础

    “依赖注入”是spring的核心特征,在Web服务器(如Tomcat)加载时,它会根据Spring的配置文件中配置的bean或者是通过注解模式而扫描并装载的bean实例自动注入到Application ...

  7. Spring2.5学习3.3_@Autowire注解实现手动装配

    @Autowired默认按类型装配,假设我在personDao 字段上加了@Autowired注解,那么就会默认取personDao 字段的类型在Spring容器中寻找与这个类型匹配的bean,寻找到 ...

  8. java代码中init method和destroy method的三种使用方式

    在java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. ...

  9. eclipse里没有j2ee

    eclipse是客户端开发工具,本来就不带有j2ee的jar包,需要容器:比如tomcat来提供这个jar的.j2EE通用jar包列表:IKIKAnalyzer3.2.8.jar // 分词器ant- ...

随机推荐

  1. Tree( 树) 组件[2]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件.一. 异步加载如果想从数据库里获取导航内容, 那么就必须 ...

  2. DOM中的NodeList与HTMLCollection

    最近在看<Javascript高级程序设计>的时候,看到了这样一句话:“理解NodeList和HTMLCollection,是从整体上透彻理解DOM的关键所在.”,所以觉得应该写一篇关于N ...

  3. 一步一步教你使用Git

    一步一步教你使用Git 互联网给我们带来方便的同时,也时常让我们感到困惑.随便搜搜就出一大堆结果,然而总是有大量的重复和错误.小妖发出的内容,都是自己实测过的,有问题请留言. 现在,你已经安装了Git ...

  4. C#高级知识点概要(1) - 委托和事件

    本文目录: 委托 委托的简单使用 用委托实现插件式编程 多播委托 静态方法和实例方法对于委托的区别 泛型委托 Func 和 Action 委托 委托的兼容 事件 事件的基本使用 事件的标准模式 委托 ...

  5. svn的使用--解决commit冲突问题

    1.如何降低冲突解决的复杂度: 1.当文档编辑完成后,尽快提交,频繁的提交/更新可以降低在冲突发生的概率,以及发生时解决冲突的复杂度. 2.在提交时,写上明确的message,方便以后查找用户更新的原 ...

  6. Caesar cipher

    #include <iostream> using namespace std; int main() {int k,i; char s[5];  cin>>k;  for(; ...

  7. k-means均值聚类算法(转)

    4.1.摘要 在前面的文章中,介绍了三种常见的分类算法.分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应.但是很多时候上述条件得不到满足,尤其是在 ...

  8. Java学习笔记--xml构造与解析之Sax的使用

    汇总:xml的构造与解析 http://www.cnblogs.com/gnivor/p/4624058.html 参考资料:http://www.iteye.com/topic/763895 利用S ...

  9. drop,delete,truncate

    drop,truncate是ddl,数据库定义语言,不执行事务 delete是dml,数据库操作语言,有事务 drop:删除内容和定义,释放空间 delete:删除内容,不删除定义,不释放空间 tru ...

  10. 整型(int)转时间格式字符串及页面long型转时间格式字符串

    1,如果是封装的整型的话需要在后台进行处理再返回页面 处理过程是这样的 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm ...