首先说一下,因为自己还没有去研读spring的AOP的源码,只是大致知道其功能,便想着自己先手动实现一个先看看,觉得这样以后研读源码的时候会收获更多!
实现:做一个在添加注解的方法执行之前,可以先执行另一个方法。类似AOP(@Brfore),不明白的同学可以去百度下,这边只做一个简单的现实。
首先准备一个接口IEat,作为你要做的事情比如,eat():
public interface IEat {
void eat();
}
然后两个类去实现这个接口,一个是我们的主要方法(原有不可变动的功能,这边自定义了一个@DoPre注解类似于@Before)Eat,一个是我们的代理类MyProxy,代理类还需去实现InvocationHandler这个接口,并且将cook()方法放在invoker()方法前(这个方法不清楚的同学可以去百度下,他在这里是实现执行Eat中的eat()方法,这样就相当于我前置了我需要添加的方法,吃之前得先做饭):
public class Eat implements IEat {
@DoPre
@Override
public void eat() {
System.out.println("eateateat");
}
}
public class MyProxy implements InvocationHandler, IEat {
private Object object; @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
cook();
method.invoke(object);
return null;
} public MyProxy(Object object) {
this.object = object;
} @Override
public void eat() {
} private void cook() {
System.out.println("cooking");
}
}
@DoPre注解没有具体做啥,只是作为一个标记,记得加@Retention(RetentionPolicy.RUNTIME)是指运行时能通过反射找到注解:
@Retention(RetentionPolicy.RUNTIME)
public @interface DoPre {}
最后main方法作为启动器,初始化init()方法负责扫面当前包下的带有这个@DoPre注解的方法,这边的初始化写的很简单,没有去遍历其他的包和子包,一切求简,可以自己优化很多地方:
public class Test {
public static IEat eat; //start
public static void main(String[] args) {
init();
eat.eat();
} private static void init() {
Class clazz = Test.class;
String packagePath = clazz.getResource("").getPath();
String packagename = clazz.getPackage().getName();
File file = new File(packagePath);
if (file.isDirectory()) {
File[] files = file.listFiles();
assert files != null;
for (File file1 : files) {
try {
StringBuilder stringBuilder = new StringBuilder(packagename);
stringBuilder.append(".").append(file1.getName());
String s = stringBuilder.toString().replace(".class", "");
Class clazz1 = Class.forName(s);
Method[] methods = clazz1.getMethods();
for (Method method : methods) {
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
//找到注解方法
if (annotation.toString().contains("DoPre")) {
//传入被代理的实例clazz1.newInstance()
IEat proxy = (IEat) Proxy.newProxyInstance(Test.class.getClassLoader(), MyProxy.class.getInterfaces(), new MyProxy(clazz1.newInstance()));
//注入对象
eat = proxy;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} } }
自己本身也是个新人,所以望大佬们见谅,代码并没有写得完美,更像是演示一这个功能,但是核心思想应该是差不多的,而且越简单可以让同学理解更快,我们学习的更应该是思想!
Java通过JDK动态代理简单的实现一个AOP的更多相关文章
-
深度剖析java中JDK动态代理机制
https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...
-
[编织消息框架][JAVA核心技术]jdk动态代理
需要用到的工具 jdk : javac javap class 反编译 :JD-GUI http://jd.benow.ca/ import java.lang.reflect.Invocation ...
-
JDK动态代理简单小程序
Jdk动态代理 1.动态代理使用的情况:需要在多个方法上加上相同的逻辑的时候,需要用到动态代理. 原因:在多个方法上写相同的逻辑,第一费事,第二在不用的时候维护麻烦 使用动态代理需要用到两个类:分别为 ...
-
java之JDK动态代理
© 版权声明:本文为博主原创文章,转载请注明出处 JDK动态代理: JDK动态代理就是在程序运行期间,根据java的反射机制自动的帮我们生成相应的代理类 优势: - 1. 业务类只需要关注业务逻辑本身 ...
-
aop学习总结一------使用jdk动态代理简单实现aop功能
aop学习总结一------使用jdk动态代理实现aop功能 动态代理:不需要为目标对象编写静态代理类,通过第三方或jdk框架动态生成代理对象的字节码 Jdk动态代理(proxy):目标对象必须实现接 ...
-
Java基础-jdk动态代理与cglib动态代理区别
JDK动态代理 此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑. 代理模式在实际使用时需要指定具体的目标对象 ...
-
JDK动态代理简单使用(2)
JDK动态代理使用: 使用JDK动态代理步骤: ①创建被代理的接口和类: public interface IA { void f1(String param); } public class A i ...
-
Java基础-JDK动态代理
JDK的动态代理依靠接口实现 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代 ...
-
设计模式之动态代理(Java的JDK动态代理实现)
先来看一下思维导图: 对于JDK的动态代理,孔浩老师说学习的方法是把它记下来. 先写一个主题接口类,表示要完成的一个主题. package com.liwei.dynaproxy; /** * 要代理 ...
随机推荐
-
安卓Design包之AppBar和Toolbar的联用
前面讲了Design包的的CoordinatorLayout和SnackBar的混用,现在继续理解Design包的AppBar; AppBarLayout跟它的名字一样,把容器类的组件全部作为AppB ...
-
Struts2中Action接收参数的四种形式
1.Struts2的Action接收参数的三种形式. a. 使用Action的属性接收(直接在action中利用get方法来接收参数): login.js ...
-
BZOJ4170 极光(CDQ分治 或 树套树)
传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...
-
JavaScript数组定义
数组有四种定义的方式 使用构造函数: var a = new Array(); var b = new Array(8); var c = new Array("first", & ...
-
Apache MINA(一)
Apache MINA is a network application framework which helps users develop high performance and high s ...
-
text-overflow 与 word-wrap:设置使用一个省略标记...标示对象内文本的溢出。
text-overflow 与 word-wrap text-overflow用来设置是否使用一个省略标记(...)标示对象内文本的溢出. 语法: 但是text-overflow只是用来说明文字溢出时 ...
-
ajax 简单操作
<script> $(function () { //$("#send").click(function () { // $.get("JQuery.as ...
-
Laravel5使用QQ邮箱发送邮件配置
在.env文件中设置如下MAIL_DRIVER=smtpMAIL_HOST=smtp.qq.comMAIL_PORT=465MAIL_USERNAME=00000000000@qq.comMAIL_P ...
-
Elasticsearch日志分析系统
Elasticsearch日志分析系统 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是Elasticsearch 一个采用Restful API标准的高扩展性的和高可用性 ...
-
C# ConcurrentStack实现
我们通过C# Queue 和Stack的实现知道Stack是依靠数组实现的,那么ConcurrentStack的栈又是如何实现的了,然后它的线程安全又是怎么做到的了? 来看看其code吧 public ...