使用Java原生代理实现数据注入

本文由博主原创,转载请注明出处
完整源码下载地址 https://github.com/MatrixSeven/JavaAOP
上一篇,我们说了使用Java原生代理实现AOP的简单例子,然么就不得不说一下Annotation这个东西了.注解(Annotation)是什么.吓得小柒君赶忙百度下:
html

  1. 注解基础知识点
  2. 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及之后版本引入的一个特性,与类、接口、枚举是在同一个层次。它能够声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
    做用分类:
  3. 编写文档:经过代码里标识的元数据生成文档【生成文档doc文档】
  4. 代码分析:经过代码里标识的元数据对代码进行分析【使用反射】
  5. 编译检查:经过代码里标识的元数据让编译器可以实现基本的编译检查【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来声明注解目标,java

@Retention用来讲明该注解类的生命周期.git

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,加上注解后的样子就是:
github

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);
    }
}

火烧眉毛运行下:
ide

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
this

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.因此我们简单修改下这个就行了
修改后的样子:code

/***
     * 获取对象方法
     * @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….看起来完美了,,赶忙跑起来试一试..
htm

不对..以前的方法拦截太罗嗦,我们只拦截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

相关文章
相关标签/搜索