使用Java原生代理实现数据注入
本文由博主原创,转载请注明出处
完整源码下载地址 https://github.com/MatrixSeven/JavaAOP
上一篇,咱们说了使用Java原生代理实现AOP的简单例子,然么就不得不说一下Annotation这个东西了.注解(Annotation)是什么.吓得小柒君赶紧百度下:
- 注解基础知识点
- 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
作用分类: - 编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
- 代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
- 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
and so on….如果你对注解(Annotation)还没有了解请左移百度百科:Annotation和Java 注解
啊,,是不是很眼熟,这个不就是经常看到的那个@Override神马的么…原来这个东西就叫做注解啊.
—–引至百度:我个人使用的理解,annotation是一种在类、类型、属性、参数、局部变量、方法、构造方法、包、annotation本身等上面的一个附属品(ElementType这个枚举中有阐述),他依赖于这些元素而存在,他本身并没有任何作用,annotation的作用是根据其附属在这些对象上,根据外部程序解析引起了他的作用,例如编译时的,其实编译阶段就在运行:java Compiler,他就会检查这些元素,例如:@SuppressWarnings、@Override、@Deprecated等等;
的确是,但是想想Spring的IOC依赖注入,控制反转@xxx(xxx=xxx)然后Bean里就被赋值了,是不是觉得好帅,哈,是不是也觉得好神奇?
是不是我创建一个注解,然后把他作用到类上就能赋值了?赶紧试一试…
首先,创建一个注解,用关键字@interface来声明,这是一个注解类.@Target来声明注解目标,
@Retention用来说明该注解类的生命周期.
package proxy.annon;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface Seven {
public String value() default "小黑";
public String Property() default "无属性";
}
然后还用咱们昨天的写的JavaBean,加上注解后的样子就是:
package proxy;
import proxy.annon.Seven;
import proxy.imp.AnimalInterface;
public class DogImp implements AnimalInterface {
@Seven(value = "Lumia")
private String name;
private String Property;
public DogImp() {
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void say() {
System.out.println("小狗:汪汪汪汪.....");
}
@Override
@Seven(Property = "水陆两栖战士")
public void setProperty(String Property) {
this.Property = Property;
}
@Override
public void getProperty() {
System.out.println(this.name + this.Property);
}
}
迫不及待运行下:
package proxy;
public class Test {
public static void main(String[] args) {
DogImp dogImp = new DogImp();
System.out.println(dogImp.getName());
dogImp.getProperty();
}
}
输出:
null
nullnull
额.好伤心,表示并没有什么效果,那@的注入到底是怎么实现的呢….
转了一圈,还得依赖咱们的反射大军哈哈…..
赶紧改造下昨天的Demo,让其能够注解..咱们一起来…
注解已经创建好了,怎么让咱们的注解产生效果呢,赶紧动手写个AnnoInjection类.
用来实现注解的内容的注入..
但是要注意,让注如属性的时候,一定要有对用的get/set方法,如果访问级别为private则可以直接使用
属性的set(obj, value),如果为public,则需要自己获取方法,然后调用方法的invoke
package proxy.annon;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class AnnoInjection {
public static Object getBean(Object obj) {
try {
// 获得类属性
Field f[] = obj.getClass().getDeclaredFields();
// 遍历属性
for (Field ff : f) {
// 获得属性上的注解
Seven s = ff.getAnnotation(Seven.class);
if (s != null) {
System.err.println("注入" + ff.getName() + "属性" + "tt" + s.value());
// 反射调用public set方法,如果为访问级别private,那么可以直接使用属性的set(obj,
// value);
obj.getClass()
.getMethod("set" + ff.getName().substring(0, 1).toUpperCase() + ff.getName().substring(1),
new Class[] { String.class })
.invoke(obj, s.value());
}
}
// 获得所有方法
Method m[] = obj.getClass().getDeclaredMethods();
for (Method mm : m) {
// 获得方法注解
Seven s = mm.getAnnotation(Seven.class);
if (s != null) {
System.err.println("注入" + mm.getName() + "方法" + "t" + s.Property());
mm.invoke(obj, s.Property());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
}
这样呢,就实现了属性的方法的注入..在哪里调用呢…….
哦,,查看之前的AnimalFactory代码,会发现在getAnimalBase里有
Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new AOPHandle(obj,method))
很明显,咱们的动态代理new AOPHandle(obj,method)时传入了反射生成obj.然后实现代理拦截直接,
咱们来先处理这个obj.所以咱们简单修改下这个就好了
修改后的样子:
/***
* 获取对象方法
* @param obj
* @return
*/
private static Object getAnimalBase(Object obj,AOPMethod method){
//获取代理对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new AOPHandle(AnnoInjection.getBean(obj),method));
}
soga….看起来完美了,,赶紧跑起来试一试..
不对..之前的方法拦截太罗嗦,咱们只拦截getProperty方法..好吧
要不然输出太恶心了….
修改后的AOPTest….
package proxy;
import java.lang.reflect.Method;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import proxy.imp.AOPMethod;
import proxy.imp.AnimalInterface;
@RunWith(BlockJUnit4ClassRunner.class)
public class AOPTest {
public static void main(String[] args) {
AnimalInterface dog = AnimalFactory.getAnimal(DogImp.class, new AOPMethod() {
// 这里写方法执行前的AOP切入方法
public void before(Object proxy, Method method, Object[] args) {
if (method.getName().equals("getProperty")) {
System.err.println("成功拦截" + method.getName() + "方法,启动");
}
}
// 这里系方法执行后的AOP切入方法
public void after(Object proxy, Method method, Object[] args) {
if (method.getName().equals("getProperty"))
System.err.println("成功拦截" + method.getName() + "方法,结束");
}
});
dog.say();
String name1 = "我的名字是" + dog.getName();
System.out.println(name1);
dog.setName("二狗子");
String name2 = "我的名字是" + dog.getName();
System.out.println(name2);
dog.getProperty();
}
}
然后给我run起来….
beauty,成功出来了呢..赶紧上个图,高兴下..

哈哈哈……大家是够有许多感悟呢,咱们下次再见
吾爱Java(QQ群):170936712
使用Java原生代理实现数据注入的更多相关文章
- 使用Java原生代理实现AOP
### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...
- 23个适合Java开发者的大数据工具和框架
转自:https://www.yidianzixun.com/article/0Ff4gqZQ?s=9&appid=yidian&ver=3.8.4&utk=6n9c2z37 ...
- [转]Java动态代理
动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...
- 《Java设计模式》之代理模式 -Java动态代理(InvocationHandler) -简单实现
如题 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式可细分为如下, 本文不做多余解释 远程代理 虚拟代理 缓冲代理 保护代理 借鉴文章 ht ...
- Java动态代理——框架中的应用场景和基本原理
前言 之前已经用了5篇文章完整解释了java动态代理的原理,本文将会为这个系列补上最后一块拼图,展示java动态代理的使用方式和应用场景 主要分为以下4个部分 1.为什么要使用java动态代理 2.如 ...
- Java 动态代理原理图解 (附:2种实现方式详细对比)
动态代理在 Java 中有着广泛的应用,例如:Spring AOP 面向切面编程,Hibernate 数据查询.以及 RPC Dubbo 远程调用等,都有非常多的实际应用@mikechen 目录 ...
- Java 动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- Java动态代理全面分析
代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ...
- 学习AOP之JAVA的代理机制
从一个输出日志的实例分析JAVA的代理机制 一.通用的日志输出方法 :需要在每个类里都增加对输出日志信息的代码 二.通过面向接口编程实现日志的输出(JAVA的静态代理):虽然实现了业务逻辑与输出日志 ...
随机推荐
- Mac与Linux的一个巨大不同
就是Mac仍处在桌面市场的商业圈里,尽管它的市场很小,但是正版率却很高,而且还有专门的Mac Store提供付费下载. Linux在桌面市场几乎没有份额,也不会有人会去买它的应用软件,基本上只存在于服 ...
- 208. Implement Trie (Prefix Tree)
题目: Implement a trie with insert, search, and startsWith methods. 链接: http://leetcode.com/problems/i ...
- Java的类演进过程
1.从面向过程到面向对象 在大家最熟悉的C语言中,如果要定义一个复杂的数据类型就用结构体(Struct)来实现,而为结构体的每个操作都定义一个函数,这个函数与结构体本身的定义没有任何关系.程序的重心集 ...
- 【HDOJ】4775 Infinite Go
其实是一道模拟题,并查集用来优化.还可以的一道题目. /* 4775 */ #include <iostream> #include <sstream> #include &l ...
- 如何将一个Form中的代码拆分到多个文件中
https://social.msdn.microsoft.com/Forums/en-US/64c77755-b0c1-4447-8ac9-b5a63a681b78/partial-class-fo ...
- 函数buf_ptr_get_fsp_addr
#define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /****************************************************** ...
- UVa 1637 (概率) Double Patience
题意: 一共有9堆牌,每堆牌四张.每次可以取堆顶点数相同的两张牌,如果有多种方案则选取是随机的. 如果最后将所有牌取完,则视为游戏胜利,求胜利的概率. 分析: 用一个九元组表示状态,分别代表每堆牌剩余 ...
- Gentoo源码安装图解
Gentoo源码安装 一.前期准备 (1)下载以下三个文件 二.配置安装环境 (1)用光盘引导到LiveCD环境 (2)配置当前LiveCD环境的网络 安装Gentoo时,服务器引导的LiveCD环境 ...
- UVA 1658 Admiral 海上将军(最小费用流,拆点)
题意: 一个有v个点的有向图,要从点1到点v需要找两条路径,两路径不可经过同一个点(除了1和v点).求这两条路径的最小费用(保证有解). 分析: 难在建图,其他套模板. 此图给的是超级复杂图,两个点之 ...
- Azure HDInsight与Hadoop周边系统集成
Sunwei 9 Dec 2014 1:54 AM 传统的Hadoop系统提供给用户2个非常优秀的框架,MR计算框架和HDFS存储框架,尽管MR已经显得有些老迈而缓慢,但是HDFS还是很多应用系统的 ...