黑马程序员--加强之动态代理

本文通过一个具体的示例展示了如何使用Java反射API创建动态代理对象。文章详细解释了如何利用Proxy类和InvocationHandler接口来实现对目标对象方法的拦截,并演示了如何在方法调用前后添加额外的操作。

-------android培训java培训、期待与您交流!     ---------- 

package cn.itcast.day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest
{

	public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
	{
		Class clazzProxy1 =
			Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);//接口的Class对象
		System.out.println(clazzProxy1.getName()); //com.sun.proxy.$Proxy0
		
		System.out.println("-----------begin constructor list -------------");
		/*
		 * list the constructors in the form of $Proxy0() or $Proxy(InvocationHadler h)
		 * */
		Constructor[] constructors = clazzProxy1.getConstructors();
		for(Constructor constructor : constructors)
		{	
			String name = constructor.getName();
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append("(");
			Class[] clazzParams = constructor.getParameterTypes();
			for(Class clazzParm : clazzParams)
			{
				sBuilder.append(clazzParm.getName()).append(",");
			}
			if(clazzParams!=null && clazzParams.length!=0)
			{
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder.toString());
			//com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)
		}
		
		System.out.println("--------------------begin methods list ----------------");
		Method[] methods = clazzProxy1.getMethods();
		for(Method method : methods)
		{
			String name = method.getName();
			StringBuilder sBuilder = new StringBuilder(name);
			Class[] clazzParamTypes = method.getParameterTypes();
			sBuilder.append("(");
			for(Class clazzParamType : clazzParamTypes)
			{
				sBuilder.append(clazzParamType.getName()).append(",");
			}
			if(0 != clazzParamTypes.length)
			{
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder.toString());
			//newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
		}
		
		System.out.println("-------------begin create instance object---------------");
		Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
		Collection proxy1 = (Collection) constructor.newInstance(new InvocationHandler()//转化为接口,即父类.向上转型
		{
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable
			{
				// TODO Auto-generated method stub
				return 10;//要与接口中的返回值一致,应返回接口的方法调用,作用于target对象
			}
		});
		//System.out.println(proxy1);
		proxy1.clear(); //no return value, no error!;
		proxy1.size(); // return int, null pointer exception
		
		System.out.println("-------------target appear-------------");
		final ArrayList target = new ArrayList();//要实现Collection接口,与proxy1一样
		Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler()
		{
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable
			{	
				//System.out.println(proxy);//??????
				System.out.println("before invoke target method.");//可封装为对象的方法
				Object retVal = method.invoke(target, args);//返回目标对象的方法调用 .此时内存中有两个此方法对象的拥用者:proxy,target
				System.out.println("after invoke target method.");
				
				return retVal;
			}
		});
		proxy2.clear();
		System.out.println(proxy2);
		proxy2.add('a');
		proxy2.add('b');
		System.out.println(proxy2.size());
		System.out.println(proxy2.getClass().getName());
		
		System.out.println("----------------封装advice方法---------------");
		Collection proxy3 = getProxy(target, new MyAdvice());
		proxy3.add("3");
		proxy3.add("4");
		proxy3.add("5");
		System.out.println(proxy3.size());
		System.out.println(proxy3.getClass().getName());
	}

	private static Collection getProxy(final ArrayList target, final Advice advice)
	{
		final Object collection = 
			Proxy.newProxyInstance(Collection.class.getClassLoader(), 
					new Class[]{Collection.class}, //必须是数组,不是可变参数形式,区别于getProxyClass();
					new InvocationHandler()
					{	
						int i = 0;
						@Override
						public Object invoke(Object proxy, Method method, Object[] args)
								throws Throwable
						{	
							advice.beforeMethod(method);
							Object retVal = method.invoke(target, args);
							advice.afterMethod(method);
							if(i++ < 1)
								System.out.println("proxy:"+proxy.hashCode());//所有对proxy对象的方法调用,都会转到这里执行;proxy对象就是要返回的对象
							else
								return retVal;
							return retVal;
						}
					});
		System.out.println("collection:"+collection.hashCode());
		return (Collection)collection;
	}

}
package cn.itcast.day3;

import java.lang.reflect.Method;

public interface Advice
{
	void beforeMethod(Method method);
	void afterMethod(Method method);
}
package cn.itcast.day3;

import java.lang.reflect.Method;

public class MyAdvice implements Advice
{
	private long start;
	
	@Override
	public void beforeMethod(Method method)
	{
		System.out.println("timing start...");
		start = System.currentTimeMillis();
	}

	@Override
	public void afterMethod(Method method)
	{
		System.out.println(method.getName()+" cost time:"+(System.currentTimeMillis()-start));
	}

}
------- android培训 java培训 、期待与您交流!     ----------  

### JavaEE 黑马程序员 学习资料 教程 下载 JavaEE 是企业级应用开发的重要技术栈,而黑马程序员提供了丰富的学习资源和教程,帮助开发者掌握 JavaEE 的核心技术和框架。以下是关于 JavaEE 黑马程序员学习资料的相关信息: #### 1. 黑马程序员官方课程资源 黑马程序员的 JavaEE 课程通常包括以下内容: - **基础部分**:涵盖 Java 基础、面向对象编程、集合框架等内容[^1]。 - **核心框架**:Spring 框架的学习,包括 Spring AOP、Spring MVC 等模块[^2]。 - **Web 开发**:涉及 Servlet、JSP、Filter 等 Web 技术[^3]。 - **数据库操作**:MyBatis、Hibernate 等 ORM 框架的使用。 - **分布式与微服务**:Dubbo、Spring Cloud 等微服务框架的学习。 这些课程资源通常可以通过黑马程序员的官方网站或其合作平台(如 Bilibili、优快云)获取。 #### 2. JDK 动态代理与 Spring AOP 在 JavaEE 开发中,Spring AOP 是一个重要的知识点。它默认使用 JDK 动态代理来实现代理功能。通过 `java.lang.reflect.Proxy` 类,可以调用 `newProxyInstance()` 方法创建代理对象[^2]。这种代理机制的优点在于可以在不修改原始代码的情况下增强某些方法的功能,实现无侵入式的代码扩展。 #### 3. SpringMVC 请求映射 SpringMVC 是 JavaEE 开发中的一个重要框架,用于处理 HTTP 请求和响应。通过 `@Controller` 和 `@RequestMapping` 注解,可以定义请求的映射路径[^3]。例如,以下代码展示了如何设置请求映射路径: ```java @Controller @RequestMapping("/user") // 类请求映射的路径 public class UserController { @RequestMapping("/commonParam") // 方法请求映射的路径 @ResponseBody public String commonParam(String name, int age) { System.out.println("name参数传递:" + name); System.out.println("age参数传递:" + age); return "success"; } } ``` #### 4. 学习资源下载 如果需要下载 JavaEE 相关的黑马程序员学习资料,可以尝试以下途径: - **官方网站**:访问黑马程序员官网,注册账号后可以下载相关课程资料。 - **第三方平台**:如 Bilibili、优快云、GitHub 等,搜索关键词“黑马程序员 JavaEE”可能找到免费或付费的课程资源。 - **论坛与社区**:加入 Java 开发者论坛或 QQ 群,与其他开发者交流并获取学习资料。 #### 5. 注意事项 在下载和使用学习资料时,请确保遵守版权法规。如果选择购买正版课程,可以获得更系统的学习体验和技术支持。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值