[原创]java WEB学习笔记104:Spring学习---AOP 前奏,通过一个问题引入动态代理
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用
内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。
本人互联网技术爱好者,互联网技术发烧友
微博:伊直都在0221
QQ:951226918
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
问题引入

1.实现
原始实现方式:
package com.jason.spring.aop.helloworld;
public interface ArithmeticCaculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
ArithmeticCaculator
package com.jason.spring.aop.helloworld;
public class fArithmeticCaculatorloggingImpl implements ArithmeticCaculator {
@Override
public int add(int i, int j) {
System.out.println("the method add begins with [" + i + ", " + j + "]");
int result = i + j;
System.out.println("the method add end with " + result);
return result;
}
@Override
public int sub(int i, int j) {
System.out.println("the method sub begins with [" + i + ", " + j + "]");
int result = i - j;
System.out.println("the method sub end with " + result);
return result;
}
@Override
public int mul(int i, int j) {
System.out.println("the method mul begins with [" + i + ", " + j + "]");
int result = i * j;
System.out.println("the method mul end with " + result);
return result;
}
@Override
public int div(int i, int j) {
System.out.println("the method div begins with [" + i + ", " + j + "]");
int result = i / j;
System.out.println("the method div end with " + result);
return result;
}
}
fArithmeticCaculatorloggingImpl
问题:
1).代码混乱:越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀. 每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.
2).代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码. 如果日志需求发生变化, 必须修改所有模块.
解决方式:动态代理
思想:代理设计模式的原理: 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.

2. 手动通过动态代理实现(实际开发中不推荐,因为难度较高)

package com.jason.spring.aop.helloworld; import java.lang.reflect.Method;
import java.util.Arrays; import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy; public class ArithmeticCaculatorLoggingProxy { //要代理的对象
private ArithmeticCaculator target; public ArithmeticCaculatorLoggingProxy(ArithmeticCaculator target) {
this.target = target;
} public ArithmeticCaculator getLoggingProxy(){
ArithmeticCaculator proxy = null; //代理对象由哪一个类加载器负责加载
ClassLoader loader = target.getClass().getClassLoader(); //代理对象的类型,即其中有那些方法
Class[] interfaces = new Class[]{ArithmeticCaculator.class}; //当调用代理对象,其中的方法时,该执行的代码
InvocationHandler invocationHandler = new InvocationHandler() {
/**
* proxy:正在返回的那个代理对象,一般情况下,在invoke 方法中都不使用对象
* method:正在被调用的方法
* args:调用方法时,传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName(); //日志
System.out.println("The method " + methodName + "begins with " + Arrays.asList(args));
//执行方法
Object result = method.invoke(target, args);
//日志
System.out.println("The method " + methodName + "end with " + result);
return result;
}
}; proxy =(ArithmeticCaculator) Proxy.newProxyInstance(loader, interfaces, invocationHandler); return proxy;
} }
测试
Main.java
package com.jason.spring.aop.helloworld;
public class Main {
public static void main(String[] args) {
/*ArithmeticCaculator arithmeticCaculator = null;
arithmeticCaculator = new ArithmeticCaculatorImpl();*/
ArithmeticCaculator target = new ArithmeticCaculatorImpl();
ArithmeticCaculator proxy = new ArithmeticCaculatorLoggingProxy(target).getLoggingProxy();
int result = proxy.add(1, 2);
System.out.println("--> " + result);
result = proxy.sub(1, 2);
System.out.println("--> " + result);
}
}
3.简便方式:使用springAOP 原理 见下一节 105
package com.jason.spring.aop.impl;
public interface ArithmeticCaculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
ArithmeticCaculator
package com.jason.spring.aop.impl; import org.springframework.stereotype.Component; @Component
public class ArithmeticCaculatorImpl implements ArithmeticCaculator { @Override
public int add(int i, int j) {
int result = i + j;
return result;
} @Override
public int sub(int i, int j) {
int result = i - j;
return result;
} @Override
public int mul(int i, int j) {
int result = i * j;
return result;
} @Override
public int div(int i, int j) {
int result = i / j;
return result;
} }
ArithmeticCaculatorImpl
package com.jason.spring.aop.impl; import java.util.Arrays;
import java.util.List; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; //把这个类声明为一个切面
//1.需要将该类放入到IOC 容器中
@Component
//2.再声明为一个切面
@Aspect
public class LoggingAspect { //声明该方法是一个前置通知:在目标方法开始之前执行 哪些类,哪些方法
//作用:@before 当调用目标方法,而目标方法与注解声明的方法相匹配的时候,aop框架会自动的为那个方法所在的类生成一个代理对象,在目标方法执行之前,执行注解的方法
//支持通配符
//@Before("execution(public int com.jason.spring.aop.impl.ArithmeticCaculatorImpl.*(int, int))")
@Before("execution(* com.jason.spring.aop.impl.*.*(int, int))")
public void beforeMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " begins " + args);
} @After("execution(* com.jason.spring.aop.impl.*.*(int, int))")
public void fterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " end " + args);
} }
LoggingAspect
<?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-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.jason.spring.aop.impl"></context:component-scan> <!-- 使 AspjectJ 注解作用:自动为匹配的类生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
aop.xml
package com.jason.spring.aop.impl; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { //1.创建Spring 的IOC 容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("aop.xml"); //2.从IOC 容器中获取 bean实例
ArithmeticCaculator arithmeticCaculator = (ArithmeticCaculator) ctx.getBean(ArithmeticCaculator.class); //3.使用bean
int result = arithmeticCaculator.add(1, 2);
System.out.println(result); result = arithmeticCaculator.div(1, 2);
System.out.println(result); } }
Main
[原创]java WEB学习笔记104:Spring学习---AOP 前奏,通过一个问题引入动态代理的更多相关文章
- [原创]java WEB学习笔记95:Hibernate 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Spring实战第八章学习笔记————使用Spring Web Flow
Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...
- Spring实战第五章学习笔记————构建Spring Web应用程序
Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- Linux内核分析第七周学习笔记——Linux内核如何装载和启动一个可执行程序
Linux内核分析第七周学习笔记--Linux内核如何装载和启动一个可执行程序 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study. ...
- 学习笔记:CentOS7学习之二十:shell脚本的基础
目录 学习笔记:CentOS7学习之二十:shell脚本的基础 20.1 shell 基本语法 20.1.1 什么是shell? 20.1.2 编程语言分类 20.1.3 什么是shell脚本 20. ...
随机推荐
- 一个列子演示vs2010 c++新特性
近日托安装雪豹的"福",格了XP装了win7,前段时间看了C++0X标准以及VS2010诱人的新特性,不禁心痒痒在线安装了VS2010,然后手写了这个列子用来测试新增的特性. st ...
- 提高C#代码质量-规范
[规范习惯]命名规范1-命名空间 使用<Company>.<Component>2-程序集不必与命名空间同名3-命名空间使用附复数4-避免与FCL的类型重名5-类型名称用名词6 ...
- 工作中的sql语句总结
1,查找mysql 数据库 自动 添加 序号 字段列1,2,3,4 ) AS rowno,ip,startcount ) b 2,mysql的分页语句 limit后面第一个参数是index,从0开始: ...
- java强制类型转换
在Java项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能.本文将对常用的转换方法进行一个总结.常用的方法有Object.toString(),(String)要转换的对象,St ...
- shell 套用expect
先用if 判断expect有没有安装 没有就yum install expect #!/bin/bash passwd='123456' /usr/bin/expect <<-EOF se ...
- php文件写入PHP_EOL与FILE_APPEND
PHP_EOL 换行符 unix系列用 \n windows系列用 \r\n mac用 \r PHP中可以用PHP_EOL来替代,以提高代码的源代码级可移植性 FILE_APPEND 用于文本追加 ...
- linux引导流程
本章重点: 1.linux引导流程 2.linux运行级别 3.linux启动服务管理 4.GRUB配置与应用 5.启动故障分析解决 linux启动流程 1.固件(fireware):固话在硬件上的程 ...
- ComboSelect 下拉筛选
Jquery Combo Select下拉筛选 http://www.dowebok.com/179.html
- OMXplayer播放视频的参数说明
1.OMXplayer支持硬解码,因此是一个非常不错的选择.2.支持格式目前知道的有:MKV.AVI.FLV.MP43.如果想用全屏播放,参数是:-r4.如果想用HDMI输出声音,参数是:-o hdm ...
- 总结-javascript-ajax
<html><head><meta charset="utf-8"><script type="text/javascript& ...