JAVA中实现简单的AOP框架功能

前言

原创文章欢迎转载,请保留出处。
若有任何疑问建议,欢迎回复。
邮箱:[email protected]

通过写一个工厂类BeanFactory负责创建配置文件config.properties中指定的目标类或者代理类的实例对象,类中方法getBean根据参数传入的字符串返回一个相应的实例对象,如果该类名是ProxyFactoryBean类则创建代理类的实例对象,否则直接调用目标类的不带参数的构造方法创建实例对象并返回,实现类似Spring框架的AOP功能。


BeanFactory类分析及代码

这个类主要通过构造方法传入一个输入流接收配置文件,另外一个主要方法getBean是整个框架的核心。这个方法先获取配置文件中需要创建的类的名字,然后先调用不带参数的构造方法创建一个实例对象(配置中的要求创建的类必须是JavaBean,否则不一定具有不带参数的构造方法),通过实例对象判断是否是ProxyFactoryBean对象,如果是,则转换成ProxyFactoryBean对象,调用ProxyFactoryBean类中方法getProxy来创建代理对象。

package maxwell_nc.aopframework;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class BeanFactory {

    Properties props = new Properties();
    public BeanFactory(InputStream ips){
        try {
            props.load(ips);//读入配置文件
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Object getBean(String key){
        //这个方法的用途是:获得一个key所指的类对象,
        //如果这个类是ProxyFactoryBean类的,即代理类,则创建代理对象并返回
        //如果不是则直接调用不带参数的构造方法创建对象返回
        String clazzname = props.getProperty(key);
        Object bean = null;
        try {
            Class clazz = Class.forName(clazzname);
            bean = clazz.newInstance();//对于javabean必须有不带参数的构造方法
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(bean instanceof ProxyFactoryBean)
        {
            //转换成ProxyFactoryBean对象,方便使用getProxy方法和set方法
            ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
            Object proxy = null;
            try {
                //取得所想建立的对象目标和Advice类
                Object target = Class.forName(props.getProperty(key+".target")).newInstance();
                Advice ad = (Advice)Class.forName(props.getProperty(key+".advice")).newInstance();
                proxyFactoryBean.setTarget(target);
                proxyFactoryBean.setAd(ad);

                proxy = proxyFactoryBean.getProxy();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return proxy;
        }
        return bean;
    }
}

ProxyFactoryBean类分析及代码

核心是getProxy利用Proxy类的静态方法newProxyInstance创建代理对象,覆盖了invoke方法,利用InvocationHandler处理方法调用。invoke方法中间插入了Advice实现类。

package maxwell_nc.aopframework;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;

public class ProxyFactoryBean {

    private Object target;
    private Advice ad;

    public Object getProxy() {
        //利用Proxy类的静态方法newProxyInstance创建代理对象
        Object proxyobj = Proxy.newProxyInstance(
        target.getClass().getClassLoader(),
        target.getClass().getInterfaces(),
        new InvocationHandler(){

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                ad.beforeMethod(method);
                Object obj = method.invoke(target, args);
                ad.afterMethod(method);
                return obj;
            }
        }
        );
        return proxyobj;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }

    public Advice getAd() {
        return ad;
    }

    public void setAd(Advice ad) {
        this.ad = ad;
    }
}

Advice接口及实现类

这个不用解析了,直接给代码,Advice接口

package maxwell_nc.aopframework;

import java.lang.reflect.Method;

public interface Advice {
    void beforeMethod(Method method);
    void afterMethod(Method method);
}

Advice实现类

package maxwell_nc.aopframework;

import java.lang.reflect.Method;

public class MyAdvice implements Advice {

    @Override
    public void afterMethod(Method method) {
        System.out.println(method.getName()+"_start");
    }

    @Override
    public void beforeMethod(Method method) {
        System.out.println(method.getName()+"_end");
    }

}

测试类和配置文件

这里我们用一个单独类来测试,我们先写一个config.properties文件

#bean=java.util.ArrayList
bean=maxwell_nc.aopframework.ProxyFactoryBean
bean.target=java.util.ArrayList
bean.advice=maxwell_nc.aopframework.MyAdvice

注意,如果使用第一行代表使用普通的bean,第二行则是创建ProxyFactoryBean,可以分别注释进行测试。下面是测试类

package maxwell_nc.aopframework;

import java.io.InputStream;
import java.util.Collection;

public class AopFrameworkTest {

    public static void main(String[] args) {
        InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
        //创建工厂
        BeanFactory beanFactory = new BeanFactory(ips);
        //获取对象并打印对应字节码名字
        Object bean = beanFactory.getBean("bean");
        System.out.println(bean.getClass().getName());
        //下面语句可以测试Advice类是否有效
        //((Collection)bean).clear();
    }

}

我们把尝试创建代理对象,并在Myeclipse中测试结果:正常获得代理对象并且调用了Advice类功能。


总结

实际上还可以把ProxyFactoryBean定义成一个接口,有许多实现这个接口的bean类,对每一个进行判断,每一种bean类都有自己的getProxy方法,更加灵活。

时间: 2024-10-05 08:51:21

JAVA中实现简单的AOP框架功能的相关文章

Java中的简单工厂模式

举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面.女娲造人,这就是简单工厂模式的应用. 首先,在这个造人的思想里面,有几个重要的角色:女娲本身.抽象的人的概念和女娲所造出的一个个具体的人. 1.)女娲是一个工厂类,也就是简单工厂模式的核心角色. 2.)具休的一个个的人,包括张三,李四等.这些人便是简单工厂模式里面的具体产品角色 3.)抽象的人是最早只存在于女娲的头

Java中的简单工厂模式(转)

Java中的简单工厂模式 举两个例子以快速明白Java中的简单工厂模式: 女娲抟土造人话说:“天地开辟,未有人民,女娲抟土为人.”女娲需要用土造出一个个的人,但在女娲造出人之前,人的概念只存在于女娲的思想里面.女娲造人,这就是简单工厂模式的应用. 首先,在这个造人的思想里面,有几个重要的角色:女娲本身.抽象的人的概念和女娲所造出的一个个具体的人. 1.)女娲是一个工厂类,也就是简单工厂模式的核心角色. 2.)具休的一个个的人,包括张三,李四等.这些人便是简单工厂模式里面的具体产品角色 3.)抽象

Java中的简单浮点数类型float和double不能够进行精确运算

在java中,简单的浮点类型float和double是不能够进行运算.我们先看下面的两个程序代码: 代码一: import java.util.Scanner; class Circle { double radius; static final double PI=3.14; public Circle(){this.radius=0;} public Circle(double r){this.radius=r;} public double getArea(){return PI*this

java创建一个简单的小框架frame

import java.awt.*; import javax.swing.*; public class SimpleFrameTest { public static void main(String[] args) { EventQueue.invokeLater(new Runnable(){ // 开一个线程 public void run() { SimpleFrame frame = new SimpleFrame(); frame.setTitle("记事本"); //

java中最简单的计算执行时长的方式

日常在做一些性能测试的时候会通过执行时间来判断执行时长,java中最简单的方式如下: //开始时间 long startL= new Date().getTime(); //这里需要导入 java.util.*;包 exceFun(); long endL= new Date().getTime(); //执行时间 System.out.println("startL:"+senStrat +" endL:"+senEndL +" 执行时长:"

java中的简单Udp通讯程序

前言 原创文章欢迎转载,请保留出处. 若有任何疑问建议,欢迎回复. 邮箱:[email protected] 本人学习java中的socket练手的小程序,高手请飘过,仅作为学习笔记,没有技术含量. 分析 这里使用两个独立线程负责发包和收包,设计两个类实现Runnable接口,利用管道和主窗体通信. 代码 mainfest.txt文件:这里注意有myqq.MyQQ后的回车符和myqq.MyQQ前的空格 Main-Class: myqq.MyQQ MyQQ.java文件: package myqq

Quartz2.2.1在JAVA中的简单用法

由于项目中需要用到定时执行任务,后来查资料发现有Quartz这么一个任务调度框架,但是网上的大部分资料几乎都是之前的版本,Quartz-2.2.1好像经过了改版,与先前的版本在用法上有那么一些出入,2.2.1里面好多方法都被弃用了,然后经过一番折腾,算是会简单的使用了.下面简单的介绍一下: 官网:http://www.quartz-scheduler.org/ 下载完进行解压会得到这六个jar包文件: 这里只介绍一下简单的用法: 1.Job接口:这个接口里面只定义了一个方法,excute voi

JAVA中常说的三大框架指:SSH

即:spring.Struts.hibernate Spring:功能强大的组件粘合济,能够将你的所有的Java功能模块用配置文件的方式组合起来(还让你感觉不到spring的存在)成为一个完成的应用 Struts:不说了,大名鼎鼎的功能强大的MVC架构 Hibernate:强大的ORM工具,然后很方便将数据库记录转化为java的实体实例,将java的实体实例很容易的保存到数据库中,如果你不需要很复杂的数据库访问,利用它你根本就不用了解数据库的细节

java中CyclicBarrier简单入门使用

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用.因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier. CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次.若在继续所有参与线程之前更新共享状态,此