05-Spring02-AOP
今日知识
1. AOP
2. AspectJ
3. JdbcTemplate
AOP
1. AOP :Aspect Oriented Programming,意为面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
1. 好处
* 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
* AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
* 经典应用:事务管理,性能监视,安全检查,缓存,日志。
* SpringAOP使用纯的java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
* AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
2. AOP实现原理
1. AOP底层将采用代理机制进行实现
2. 接口+实现类:Spring采用jdk的动态代理Proxy
3. 实现类:Spring采用cglib字节码增强
3. AOP术语
1. target:目标类,需要被代理的类。例如:UserService
2. Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
3. PointCut 切入点:已经被增强的连接点。例如:addUser()
4. advice 通知/增强,增强代码。例如:after、before
5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
6. proxy 代理类
7. Aspect(切面): 是切入点pointcut和通知advice的结合
一个线是一个特殊的面。
一个切入点和一个通知,组成成一个特殊的面。
4. 手动代理
1. JDK动态代理
* 和原来的方法一样
2. cglib增强字节码
1. 导入jar包:
2. 没有接口,只有实现类。
//cglib代理
@Test
public void test2(){
final UserService1 userService=new UserService1();
UserService1 proxy = (UserService1) Enhancer.create(UserService1.class, new InvocationHandler() {
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
System.out.println("开启事务");
Object invoke = method.invoke(userService, objects);
System.out.println("提交事务");
return invoke;
}
});
proxy.addUser();
}
5. Spring编写代理半自动
1. jar
2. 目标类
* public class UserService1 {
public void addUser() {
System.out.println("添加用户");
}
}
3. 切面类
* public class MyAspect2 implements MethodInterceptor{
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("开启事务");
Object invoke = mi.proceed();
System.out.println("提交事务");
return invoke;
}
}
4. spring配置
* <!--业务类-->
<bean id="userService" class="com.rqy.service.UserService1"/>
<!--切面类-->
<bean id="myAspect" class="com.rqy.aspect.MyAspect2"/>
<!--使用工厂bean创建代理-->
<bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="userService"/>
<property name="interceptorNames" value="myAspect"/>
</bean>
5. test
* @Autowired
@Qualifier("proxyService")
UserService1 userService;
@Test
public void test3(){
userService.addUser();
}
6. Spring编写代理半自动升级版(通过配置类方式,同时注解注入)
1. jar
2. 目标类
@Component("userService")
* public class UserService1 {
public void addUser() {
System.out.println("添加用户");
}
}
3. 切面类
* //注解注入
* @Component("mymethod")
* public class MyAspect2 implements MethodInterceptor{
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("开启事务");
Object invoke = mi.proceed();
System.out.println("提交事务");
return invoke;
}
}
4. 配置类
* //告诉spring这是一个配置类
@Configuration
public class SpringConfig {
//在配置中注册组件
//注册第三方或者已经编译过得类
//如果bean里面不写,默认方法名当做bean的id
@Bean("proxyFactoryBean")
public ProxyFactoryBean proxyFactoryBean(@Qualifier("userService") UserService userService){
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setTarget(userService);
proxyFactoryBean.setInterceptorNames("mymethod");
return proxyFactoryBean;
}
}
5. spring配置
*<!--注解开关-->
<context:component-scan base-package="com.rqy"/>
5. test
* @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:application.xml")
public class MyTest {
@Autowired
@Qualifier("proxyFactoryBean")
UserService userService;
@Test
public void test(){
userService.addUser();
}
}
AspectJ全自动编程
1. 导包
* dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
2. 切面类
public class MyAspect implements MethodInterceptor{
public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("开启事务");
Object invoke = mi.proceed();
System.out.println("提交事务");
return invoke;
}
}
Spring的AOP配置
* <!--切面类-->
<bean id="myAspect" class="com.rqy.aspect.MyAspect"/>
<!--
AOp编程步骤
1. 导入命名空间
2. proxy-target-class="true" 默认使用cglib代理
3. aop:pointcut
切入点表达式:execution(* com.rqy.*.*(..))
选择方法 包 类名任意 方法名任意 参数任意
切入面:advice-ref:通知
pointcut-ref:切入点的引入
-->
<aop:config proxy-target-class="true">
<aop:pointcut id="myPointCut" expression="execution(* com.rqy.service.*.*(..))"/>
<aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
</aop:config>
3. 测试
* @Autowired
@Qualifier("userService")
UserService userService;
@Test
public void test(){
userService.addUser();
}
AspectJ
1. AspectJ简介
* AspectJ是一个基于Java语言的AOP框架
* Spring2.0以后新增了AspectJ切点表达式的支持
* @AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
* 新版本Spring框架,建议使用AspectJ方式来开发AOP
* 主要用途:自定义开发
2. Aspect案例讲解
1. 导包
* AOP联盟规范:aopalliance
* AOP实现:spring-aop
* 规范:aspectjweaver
* aspectj实现:spring-aspects
2. 实现类:和上面一样
3. 切面类:
* public class MyAspect2 {
public void myBefore(JoinPoint jp){
System.out.println("前置通知"+jp.getSignature().getName());//连接点的方法名
}
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知 前");
//获取切入点方法名
String name = joinPoint.getSignature().getName();
System.out.println(name);
Object proceed = joinPoint.proceed();
System.out.println("环绕通知 后");
return proceed;
}
public void myAfterReturnning(JoinPoint jp,Object e){
System.out.println("后置通知:"+e);
}
public void myAfterThrowing(JoinPoint jp,Throwable e){
System.out.println("异常通知:"+e.getMessage());
}
public void myAfter(){
System.out.println("最终通知");
}
}
4. spring配置
* <!--业务类-->
<bean id="userService" class="com.rqy.service.UserService"/>
<!--切面类-->
<bean id="myAspect" class="com.rqy.aspect.MyAspect2"/>
<!--
AOp编程步骤
1. 导入命名空间
2. proxy-target-class="true" 默认使用cglib代理
3. aop:pointcut
切入点表达式:execution(* com.rqy.*.*(..))
选择方法 包 类名任意 方法名任意 参数任意
切入面:advice-ref:通知
pointcut-ref:切入点的引入
-->
<!-- <aop:config proxy-target-class="true">
<aop:pointcut id="myPointCut" expression="execution(* com.rqy.service.*.*(..))"/>
<aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
</aop:config>-->
<aop:config>
<aop:aspect ref="myAspect">
<aop:pointcut id="myPoinrCut" expression="execution(* com.rqy.service.*.*(..))"/>
<!--前置通知-->
<aop:before method="myBefore" pointcut-ref="myPoinrCut"></aop:before>
<!--环绕通知-->
<aop:around method="myAround" pointcut-ref="myPoinrCut"></aop:around>
<!--异常通知-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPoinrCut" throwing="e"></aop:after-throwing>
<!--后置通知,用于获取返回值-->
<aop:after-returning method="myAfterReturnning" pointcut-ref="myPoinrCut" returning="e"></aop:after-returning>
<!--最终通知 有没有异常都会走最终通知-->
<aop:after method="myAfter" pointcut-ref="myPoinrCut"></aop:after>
</aop:aspect>
</aop:config>
3. AspectJ基于xml的讲解
1. 上面的案例
4. AspectJ注解的讲解
1. @Aspect 声明切面,修饰切面类,从而获得 通知。
2. @Before 前置
3. @AfterReturning 后置
4. @Around 环绕
5. @AfterThrowing 抛出异常
6. @After 最终
7. 切入点 ,@PointCut ,修饰方法 private void xxx(){} 之后通过“方法名”获得切入点引用
8. xml需要开启 <!--aop注解生效-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
9. 案例
@Component
@Aspect
public class MyAspect3 {
//声明共用切入点
@Pointcut("execution(* com.rqy.service.*.*(..))")
public void myPointCut(){
}
@Before(value = "myPointCut()")
public void myBefore(JoinPoint jp){
System.out.println("前置通知"+jp.getSignature().getName());//连接点的方法名
}
@Around(value = "myPointCut()")
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知 前");
//获取切入点方法名
String name = joinPoint.getSignature().getName();
System.out.println(name);
Object proceed = joinPoint.proceed();
System.out.println("环绕通知 后");
return proceed;
}
@AfterReturning(value = "myPointCut()",returning = "e")
public void myAfterReturnning(JoinPoint jp,Object e){
System.out.println("后置通知:"+e);
}
@AfterThrowing(value = "myPointCut()",throwing = "e")
public void myAfterThrowing(JoinPoint jp,Throwable e){
System.out.println("异常通知:"+e.getMessage());
}
@After(value = "myPointCut()")
public void myAfter(){
System.out.println("最终通知");
}
}
切入点表达式
1. 语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
2. 修饰符,一般省略
public 公共方法
* 任意
返回值,不能省略
void 返回没有值
String 返回值字符串
* 任意
包,[省略]
com.gyf.crm 固定包
com.gyf.crm.*.service crm包下面子包任意 (例如:com.gyf.crm.staff.service)
com.gyf.crm.. crm包下面的所有子包(含自己)
com.gyf.crm.*.service.. crm包下面任意子包,固定目录service,service目录任意包
类,[省略]
UserServiceImpl 指定类
*Impl 以Impl结尾
User* 以User开头
* 任意
方法名,不能省略
addUser 固定方法
add* 以add开头
*Do 以Do结尾
* 任意
(参数)
() 无参
(int) 一个整型
(int ,int) 两个
(..) 参数任意
throws ,可省略,一般不写。
3. 案例1:
execution(* com.gyf.crm.*.service..*.*(..))
案例2:或
<aop:pointcut expression="execution(* com.gyf.crm.service.*.*(..)) ||
execution(* com.gyf.*Do.*(..))" id="myPointCut"/>
JdbcTemplate
1. 导包
1. 数据库驱动包
2. Spring对数据库支持的两个包
* spring-jdbc-4.2.4.RELEASE
* spring-tx-4.2.4.RELEASE
3. +1连接池 c3p0 一个 (或者JDBC 两个)
* c3p0一个包
* 或者 dbcp包+pool包
2. @Test
public void test(){
//1.创建数据源
BasicDataSource dataSource=new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring_day04?serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("123456");
//创建模板
JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
String sql="insert into t_user values (null,?,?)";
jdbcTemplate.update(sql,"tom","123");
}
3. xml配置的方式(DBCP)
* <!--dbcp数据源-->
<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_day04?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="userDao" class="com.rqy.dao.impl.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
4. xml配置的方式(C3P0)
* <!--c3p0数据源
参数不太一样
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day04?serverTimezone=UTC"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
</bean>
5. UserDaoImpl类
* public class UserDaoImpl implements UserDao {
JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void addUser(User user) {
String sql="insert into t_user values (null,?,?)";
jdbcTemplate.update(sql,user.getUsername(),user.getPassword());
}
}
6. 使用JdbcDaoSupport(优化Bean配置)
1. 每个DAO都需要声明template 而且要写set方法。所以让DAO继承与该类,不用写这部分代码了
2. dao层变化
* public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
public void addUser(User user) {
String sql="insert into t_user values (null,?,?)";
this.getJdbcTemplate().update(sql,user.getUsername(),user.getPassword());
}
}
3. xml配置的方式
* <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_day04?serverTimezone=UTC"/>
<property name="user" value="root"/>
<property name="password" value="123456"/>
</bean>
<bean id="userDao" class="com.rqy.dao.impl.UserDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
05-Spring02-AOP的更多相关文章
- 第05章 AOP细节
第05章 AOP细节 1.切入点表达式 1.1 作用 通过表达式的方式定位一个或多个具体的连接点. 1.2 语法细节 ①切入点表达式的语法格式 execution([权限修饰符] [返回值类型] [简 ...
- Spring AOP学习笔记05:AOP失效的罪因
前面的文章中我们介绍了Spring AOP的简单使用,并从源码的角度学习了其底层的实现原理,有了这些基础之后,本文来讨论一下Spring AOP失效的问题,这个问题可能我们在平时工作中或多或少也会碰到 ...
- Spring事务Transaction配置的五种注入方式详解
Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...
- Spring框架简单介绍
原文地址: http://my.oschina.net/myriads/blog/37922 1.使用框架的意义与Spring的主要内容 随着软件结构的日益庞大,软件模块化趋势出现,软件开发也须要多 ...
- JAVAEE——spring02:使用注解配置spring、sts插件、junit整合测试和aop演示
一.使用注解配置spring 1.步骤 1.1 导包4+2+spring-aop 1.2 为主配置文件引入新的命名空间(约束) 1.3 开启使用注解代替配置文件 1.4 在类中使用注解完成配置 2.将 ...
- Spring框架学习05——AOP相关术语详解
1.Spring AOP 的基本概述 AOP(Aspect Oriented Programing)面向切面编程,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.事务管理.安全检查 ...
- spring-02
spring-02 1.谈谈你对 Spring 的理解 Spring 是一个开源框架,为简化企业级应用开发而生.Spring 可以是使简单的 JavaBean 实现以前只有 EJB 才能实现的功能.S ...
- 面向切面编程AOP
本文的主要内容(AOP): 1.AOP面向切面编程的相关概念(思想.原理.相关术语) 2.AOP编程底层实现机制(动态代理机制:JDK代理.Cglib代理) 3.Spring的传统AOP编程的案例(计 ...
- PostSharp AOP
使用PostSharp 在.NET 平台上实现 AOP 摘要 本文首先介绍AOP(面向方面编程)的相关概念及理论,然后介绍如何使用PostSharp框架在.NET平台上实现AOP,最后对PostS ...
- Spring aop——前置增强和后置增强 使用注解Aspect和非侵入式配置
AspectJ是一个面向切面的框架,它扩展了java语言,定义了AOP语法,能够在编译期提供代码的织入,所以它有一个专门的编译器用来生成遵守字节码字节编码规范的Class文件 确保使用jdk为5.0以 ...
随机推荐
- 数据结构与算法 Python语言实现 第一章练习
说明:部分代码参考了Harrytsz的文章:https://blog.csdn.net/Harrytsz/article/details/86645857 巩固 R-1.1 编写一个Python函数 ...
- mysql 多主一从
一.主服务器准备 1.1.环境准备 两台主机器ip分别为 100.100.100.105 (主1) 100.100.100.106(主2) 安装 mysql [root@centos ~]# yum ...
- 与drawable的较量(一)
前言 在android ui中drawable 是一个非常关键的要点,因为我们现在使用的花里胡哨的APP,都在胡里花哨的drawable 构建的. drawable,英文翻译为可拖拽的.说白了就是自己 ...
- JAVA大数类—基础操作(加减乘除、取模、四舍五入、设置保留位数)
当基础数据类型长度无法满足需求时可以使用大数类 构造方法接受字符串为参数 BigInteger bInt = new BigInteger("123123"); BigDecima ...
- bzoj 2683 CDQ分治
题目描述 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数 ...
- hdu6621 二分加主席树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6621 Problem Description You have an array: a1, a2, ...
- (树形DP入门题)Anniversary party(没有上司的舞会) HDU - 1520
题意: 有个公司要举行一场晚会.为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司等都可以邀请. ...
- WeihanLi.Npoi 根据模板导出Excel
WeihanLi.Npoi 根据模板导出Excel Intro 原来的导出方式比较适用于比较简单的导出,每一条数据在一行,数据列虽然自定义程度比较高,如果要一条数据对应多行就做不到了,于是就想支持根据 ...
- python3操作PyMySQL笔记
python3操作mysql需要先安装PyMySQL pip install PyMySQL 在linux登录mysql ,并且在安装数据库时设置了数据库的用户名“root”和密码“root”,mys ...
- leetcode 全解(python版)
本着blabla的精神,在这里(可能会)给出leetcode的全部习题答案 --持续更新中... 1.给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整 ...