本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用

内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。

本人互联网技术爱好者,互联网技术发烧友

微博:伊直都在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 前奏,通过一个问题引入动态代理的更多相关文章

  1. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. [原创]java WEB学习笔记66:Struts2 学习之路--Struts的CRUD操作( 查看 / 删除/ 添加) 使用 paramsPrepareParamsStack 重构代码 ,PrepareInterceptor拦截器,paramsPrepareParamsStack 拦截器栈

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  5. Spring实战第五章学习笔记————构建Spring Web应用程序

    Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...

  6. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  7. Spring 源码学习笔记11——Spring事务

    Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...

  8. Linux内核分析第七周学习笔记——Linux内核如何装载和启动一个可执行程序

    Linux内核分析第七周学习笔记--Linux内核如何装载和启动一个可执行程序 zl + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study. ...

  9. 学习笔记:CentOS7学习之二十:shell脚本的基础

    目录 学习笔记:CentOS7学习之二十:shell脚本的基础 20.1 shell 基本语法 20.1.1 什么是shell? 20.1.2 编程语言分类 20.1.3 什么是shell脚本 20. ...

随机推荐

  1. sql 动态行转列

    create table u01 (医案编号 varchar(5),药物编号 varchar(5)) insert into u01 select '01','01' union all select ...

  2. 【改】iOS学习之NSAttributedString(富文本)

    NSAttributedString 叫做富文本,是一种带有属性的字符串,通过它可以轻松的在一个字符串中表现出多种字体.字号.字体大小等各不相同的风格,还可以对段落进行格式化,一般都是对可变富文本(N ...

  3. phpunit学习 3:

    16:17 2015/12/11phpunit学习 3:单元测试的大概步骤是:编写待测试类,编写测试用例类,编写测试类,测试.1.如果你有多个类,多个测试类的test类,那么可以编写一个AllTest ...

  4. Kinect的那些事儿

    Kinect结合Unity3d跑酷游戏体感Demo 今天收拾东西,在柜子的翻出了一台崭新的Kinect,说起来真是惭愧,大学毕业那会儿,慈老师(和名字一位慈祥的好老师,也是我的毕业设计指导老师)赞 助 ...

  5. HDU 3743 Frosh Week (线段树+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 Frosh Week Time Limit : 2000/1000ms (Java/Other) ...

  6. Browsersync — 省时的浏览器同步测试工具

    Browsersync能让浏览器实时.快速响应您的文件更改(html.js.css.sass.less等)并自动刷新页面.更重要的是 Browsersync可以同时在PC.平板.手机等设备下进项调试. ...

  7. PHP TCPDF ERROR: [Image] Unable to get image解决办法详解

    使用TCPDF输出pdf文件时,有时会直接显示pdf文件不可显示,仔细调试之下会报错TCPDF ERROR: [Image] Unable to get image.问题出现Image()函数中.第一 ...

  8. 试验删除RAC(ORA10G)节点

    1.环境概述 2.删除一个节点 本实验中以删除第二个节点为示例. 2.1删除数据库实例 在第一个节点上(存活的节点)上使用DBCA删除第二个节点的实例. 执行完以上操作可以看下crs_stat –t  ...

  9. 重学ps_1

    1,选取 打开图片->点击选取工具->ctrl+c->ctrl+n->ctrl+v 2,去除图片背景 打开你要去除背景的图片->在图层面板中->双击图层把图层改为0 ...

  10. DevOps is dirty work - CI drives you crazy

    一直很想谈谈Continuous Integration(CI),持续集成. 就在不久前一次朋友聚会上,一个刚刚跳槽到一家创业公司的朋友跟我抱怨说他们没有CI,没有code review,要做点事太累 ...