Java反射—模拟Spring的Aop

1.    大概流程

  上篇文章已经结合Java反射解释了SpringAop的原理,这里我们简单模拟以下Spring的Aop实现。大体流程如下:

  ?  创建一个properties配置文件模拟Spring配置文件。

  ?  创建一个增强接口与一个实现类模拟Spring的Advice。

  ?  创建一个生成代理的工厂类,并在InvocationHandler类的invoke方法中织入增强方法(即aop)。

  ?  创建一个生成Bean的工厂类(类似IOC工厂,只创建bean,没有依赖注入的功能),生成Bean时判断,如果是Spring管理的类,则返回目标对象的代理对象,如果不是spring管理的类则直接返回目标对象。理论不再多说,直接看代码:

2.    实例代码

  2.1   配置文件(config.properties):

#1、模拟没有被spring管理的bean的class
xxx=java.util.ArrayList
#2、模拟被Spring管理的bean的class
#xxx=cn.itcast.day3.aopframework.ProxyFactoryBean

#3、xxx的增强类
xxx.advice=cn.itcast.day3.aopframework.MyAdvice
#4、xxx的目标类
xxx.target=java.util.ArrayList

  2.2  增强接口:

package cn.itcast.day3.aopframework;

import java.lang.reflect.Method;

/**
 * 增强接口
 *
 * @author wangzhipeng
 *
 */
public interface Advice {
	// 前置增强方法
	void beforeMethod(Method method);

	// 后置增强方法
	void afterMethod(Method method);
}

  2.3  增强实现:

package cn.itcast.day3.aopframework;

import java.lang.reflect.Method;

/**
 * 增强类
 *
 * @author wangzhipeng
 *
 */
public class MyAdvice implements Advice {
	long beginTime = 0;

	/**
	 * 前置增强方法
	 */
	public void beforeMethod(Method method) {
		System.out.println("到TGB来学习啦!");
		beginTime = System.currentTimeMillis();
	}

	/**
	 * 后置增强方法
	 */
	public void afterMethod(Method method) {
		System.out.println("从TGB毕业上班啦!");
		long endTime = System.currentTimeMillis();
		System.out.println(method.getName() + " running time of " + (endTime - beginTime));

	}

}

  2.4  生成代理的工厂类:

package cn.itcast.day3.aopframework;

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

/**
 * 生成代理的工厂类
 *
 * @author wangzhipeng
 *
 */
public class ProxyFactoryBean {
	// 增强对象
	private Advice advice;
	// 目标对象
	private Object target;

	// 获取目标对象的代理对象
	public Object getProxy() {
		Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
			// InvocationHandler接口的匿名内部类
			// 执行代理对象的任何方法时都将被替换为执行如下invoke方法
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

				advice.beforeMethod(method);// 执行【前置】增强方法
				Object retVal = method.invoke(target, args);// 执行目标方法
				advice.afterMethod(method);// 执行【后置】增强方法

				return retVal;// 返回目标方法执行结果,代理对象的方法返回值必须与目标对象的方法返回值相同
			}
		});
		return proxy;
	}

	public Advice getAdvice() {
		return advice;
	}

	public void setAdvice(Advice advice) {
		this.advice = advice;
	}

	public Object getTarget() {
		return target;
	}

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

}

  2.5  生成Bean的工厂类(类似IOC工厂,这里只能创建bean,没有依赖注入)

package cn.itcast.day3.aopframework;

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

/**
 * 模拟Spring的IOC工厂(只提供创建bean功能,不能依赖注入)
 *
 * @author wangzhipeng
 *
 */
public class BeanFactory {
	Properties props = new Properties();

	/**
	 * 实例化Bean工厂时会扫描我们的配置文件(传入我们的配置文件)
	 *
	 * @param ips
	 *            配置文件的stream流
	 */
	public BeanFactory(InputStream ips) {
		try {
			props.load(ips);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 生产bean
	 *
	 * @param name
	 *            bean的名称
	 */
	public Object getBean(String name) {
		String className = props.getProperty(name);
		Object bean = null;
		try {
			// 反射获取类名为name的对象
			Class clazz = Class.forName(className);
			bean = clazz.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 如果目标被Spring管理了(这里以如果bean是ProxyFactoryBean类型的对象代替)则返回目标的代理对象,否则直接返回目标对象
		// 实际的Spring中,可以用spring的配置文件或者注解来判断是否被spring管理
		if (bean instanceof ProxyFactoryBean) {
			Object proxy = null;
			ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean) bean;
			try {
				// 反射获得增强对象
				Advice advice = (Advice) Class.forName(props.getProperty(name + ".advice")).newInstance();
				// 反射获得目标对象
				Object target = Class.forName(props.getProperty(name + ".target")).newInstance();
				// 生成目标对象的代理对象,并织入增强方法,实现了aop
				proxyFactoryBean.setAdvice(advice);
				proxyFactoryBean.setTarget(target);
				proxy = proxyFactoryBean.getProxy();
			} catch (Exception e) {
				e.printStackTrace();
			}
			return proxy;// 如果目标被spring管理,则返回目标的代理对象
		}
		return bean;// 如果没有被spring管理,直接返回目标
	}
}

  2.6  测试类

package cn.itcast.day3.aopframework;

import java.io.InputStream;

/**
 * 测试类
 *
 * @author wangzhipeng
 *
 */
public class AopFrameworkTest {

	public static void main(String[] args) throws Exception {
		// 获得配置文件的stream流
		InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
		// 利用bean工厂创建配置文件中配置的类的对象
		Object bean = new BeanFactory(ips).getBean("xxx");
		// 测试BeanFactory生成的是目标还是代理,如果是代理会执行增强方法
		System.out.println(bean.getClass().getName());
		bean.hashCode();
	}
}

  2.7  测试结果1:

  如果配置文件中配置的是“xxx=cn.itcast.day3.aopframework.ProxyFactoryBean “,则结果为

  

  说明返回的是代理对象,而且执行了增强方法。(因为我们的BeanFactory中有相关的判断【if(bean instanceof ProxyFactoryBean)】)。

  2.8   测试结果2

  如果配置文件中配置的是“xxx=cn.itcast.day3.aopframework.ProxyFactoryBean “,则结果为

  

  说明返回的是目标对象,而且没有执行增强方法。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-27 13:53:38

Java反射—模拟Spring的Aop的相关文章

采用dom4j和反射模拟Spring框架的依赖注入功能

Spring的依赖注入是指将对象的创建权交给Spring框架,将对象所依赖的属性注入进来的行为.在学习了dom4j后,其实也可以利用dom4j和反射做一个小Demo模拟Spring框架的这种功能.下面是具体的步骤: 第一步,编写配置文件.配置文件的书写,采用了和Spring的配置文件applicationContext.xml一样的书写规则: <?xml version="1.0" encoding="UTF-8"?> <!-- applicati

JAVA 反射 动态代理与AOP

摘自 b站尚硅谷JAVA视频教程 原文地址:https://www.cnblogs.com/superxuezhazha/p/12358469.html

java proxy InvocationHandler 模拟 spring aop

在学习spring的aop的时候,老师叫我们使用java的proxy和InvocationHandler来模拟spring的aop. 首先要了解什么是代理:所谓代理就是我想让小王去买包烟,但是我又不想直接通知小王,因为那样我感觉自己非常的掉价.所以我就叫小李去通知小王,让小王完成这件事.在这个过程中,我是一个主动方,小王是一个行为执行方,而小李就是一个代理.因为小李负责我和小王之间的关系,甚至小李也可以叫小王给自己再买一包烟(实际这就是动态代理的最大用处). 动态代理模式有代理对象,被代理对象.

模拟spring - 动手写一个spring AOP

一.前言 AOP (Aspect Oriented Programing) - 面向切面编程,它主要用于日志记录.性能分析.安全控制.事务处理.异常处理等方面. AOP主要使用JDK的反射和动态代理,AOP代理其实是由AOP框架动态生成的一个对象,该对象可作为目标对象使用,AOP代理包含了目标对象的全部方法,但AOP代理的方法与目标对象的方法存在差异:AOP方法在特定切入点添加了增强处理,并回调了目标对象的方法. 动态代理的文章请参考:http://blog.csdn.net/zdp072/ar

Java动态代理--&gt;Spring AOP

引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Java基础知识,希望对大家有所帮助.): [1] Java反射知识-->Spring IoC :http://www.iteye.com/topic/1123081 [2] Java动态代理-->Spring AOP :http://www.iteye.com/topic/1123293 [3] 属性

Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring

IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合.我们还可以对某对象所需要的其它对象进 行注入,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制, Spring还充当了工厂的角色,我们不需要自己建立工厂类.S

利用反射模拟一个spring的内部工作原理

这个简单的案例是实行了登录和注册的功能,没有链接数据库. 在bean中id 是唯一的,id和name的区别在于id不能用特殊字符而name可以用特殊字符,比如:/-\.... 1 package com.obtk.reflect; 2 3 public class Logon { 4 /** 5 * 帐号密码长度大于六位字符就成功,否则失败! 6 * */ 7 public String select(String name, String pass) { 8 if (name.length()

Java 模拟Spring

一.概述 1.目标:模拟Spring的Ioc 2.用到的知识点:利用jdom的xpath读取xml文件,反射 二.有如下文件: 1.applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans> <bean id="vehicle" class="com.tong.spring.factory.Car"> </

Spring源码阅读:使用标准AOP的API模拟Spring AOP + AspectJ的设计与实现

在上一篇博客中,提到了标准AOP与Spring AOP.这一篇就来把他们模拟出来. 在模拟之前,还需要提及的是,在Spring框架中,对于AOP的支持: Spring 支持的AOP AspectJ是另外一个有名的AOP框架,Spring也集成AspectJ,同时Spring AOP与AspectJ有一定程度的集成,这样一来Spring中就支持两种AOP:1)Spring AOP.2)AspectJ.而使用AOP的方式却又三种: 1)完全使用Spring AOP 2)完全使用AspectJ(分为注