SpringTest2

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) AOPOOP 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开发依赖 asmjar 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 SpringAOP扩展支持 

整合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/nameuserService对象所有方法 

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 提供切面,可以包括多个通知和多个切入点

面试题: aspectaspectJ区别 ?

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() , 必须同时满足 pointcut1pointcut2 切入点表达式 

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

6.  Spring JdbcTemplate 

 学习spring 重点三--- 六章 

第三章:核心技术: IoCAOP 

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

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

第六章:整合 

6.1.  JdbcTemplate 快速入门 

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

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

4个核心

2个日志

1web集成

1junit集成

1inject 

4AOP 

导入 jdbctx 2jar包 

导入 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 pooljar包 

配置 

6.2.3.  C3P0连接池 CombopooledDataSource 使用

导入c3p0jar包 

配置

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、 IoCDI的概念和区别? IoC是如何实现的 ?

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

3、 BeanFactoryFactoryBean的区别 ?

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

5、 BeanPostProcessor 后处理的作用 ?

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

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

8、 传统Spring AOP 开发和配置 

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

10、 advisoradviceaspect 区别

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

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

原文地址:https://www.cnblogs.com/wangchuanfu/p/5658332.html