`
Cindy_Lee
  • 浏览: 110173 次
  • 性别: Icon_minigender_1
  • 来自: 武汉人在北京
社区版块
存档分类
最新评论

注解+动态代理的一个例子

阅读更多

在公司没事干了,学习下动态代理模式(关于代理的基础只是有很多帖子都有我就不重复了),做了个注解动态代理的例子,给那些学习注解或动态代理的初学者。

花了将近1小时,没做个什么优化,大牛勿喷。

几个主要的类:

注解类:

package test2;

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.METHOD)
public @interface ProxyTag {
	public Class proxyClass();
}
 

代理类父类:

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

public abstract class  ProxyBean implements InvocationHandler{
	
	private Object o;

	
	private String methodName;
	
	public Object bind(Object obj,String methodName){
		this.o = obj;
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
	}
	
	
	public Object invoke(Object proxy, Method method, Object[] obj)
			throws Throwable {
		if(method.getName().equals(methodName)){
			this.before();
			Object result = method.invoke(o, obj);
			this.after();
			return result;
		}else{
			Object result = method.invoke(o, obj);
			return result;
		}
		
	}
	
	public abstract void before();
	
	public abstract void after();
}

代理工厂:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ProxyFactory {
	
	
	public static <T> T getProxyBean(Class<T> clazz){
		T t = (T) newInstance(clazz);
		Method[] methods = clazz.getMethods();
		
		for(int i=0;i<methods.length;i++){
			ProxyTag pt = methods[i].getAnnotation(ProxyTag.class);
			if(pt == null){
				continue;
			}
			ProxyBean pb = (ProxyBean) newInstance(pt.proxyClass());
			t = (T) pb.bind(t, methods[i].getName());
		}
		return t;
	}
	
	private static Object newInstance(final Class clazz){
		try {
			Constructor cons = clazz.getConstructor();
			return cons.newInstance(new Class[]{});
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}

 测试类:

 

package test2;

public class ProxyClass extends ProxyBean{

	public void after() {
		System.out.println("after....");
	}

	public void before() {
		System.out.println("before....");
	}
}

 

public class ProxyClass2 extends ProxyBean{

	public void after() {
		System.out.println("after2....");
	}

	public void before() {
		System.out.println("before2....");
	}
}
 
public interface IDemo {
	public void sayHello();
	public void sayHello2();
}
 
public class Demo implements IDemo{
	
	@ProxyTag(proxyClass=ProxyClass.class)
	public void sayHello(){
		System.out.println("hello....");
	}
	
	@ProxyTag(proxyClass=ProxyClass2.class)
	public void sayHello2(){
		System.out.println("hello2....");
	}
}
public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		IDemo demo = ProxyFactory.getProxyBean(Demo.class);
		demo.sayHello();
		System.out.println("-----------------------------");
		demo.sayHello2();

	}

}
before....
hello....
after....
-----------------------------
before2....
hello2....
after2....
我没有看过spring的拦截器源码,不过实现原理上估计差不多,需要源码请下载附件
刚刚发现代码有点笔误的地方,容易让人误解,展示的代码已经修改过来了,附件里的代码请自己对照着修改一下
分享到:
评论
10 楼 ucfjepl 2011-03-19  
liuyes 写道
相当不错,注释很强大

的确非常强大.....
9 楼 Cindy_Lee 2011-03-17  
baiweiyll 写道
      
    用这种吧 Method[] methods = clazz.getDeclaredMethods();
    少循环几次

呵呵很有道理,是我疏忽了
8 楼 baiweiyll 2011-03-17  
      
    用这种吧 Method[] methods = clazz.getDeclaredMethods();
    少循环几次
7 楼 Cindy_Lee 2011-03-16  
jeho0815 写道
ProxyTag pt = methods[i].getAnnotation(ProxyTag.class); 这句话有问题啊。。。

啥问题 望指教
6 楼 jeho0815 2011-03-16  
ProxyTag pt = methods[i].getAnnotation(ProxyTag.class); 这句话有问题啊。。。
5 楼 liuyes 2011-03-16  
相当不错,注释很强大
4 楼 t42dw 2011-03-16  
<div class="quote_title">Cindy_Lee 写道</div>
<div class="quote_div">
<div class="quote_title">t42dw 写道</div>
<div class="quote_div">
<p> </p>
<div class="quote_div">我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass </div>
<p> </p>
<p><span>demo.sayHello();   </span></p>
<p><span>        System.out.println(</span><span class="string">"-----------------------------"</span><span>);   </span></p>
<p><span>        demo.sayHello2();   </span></p>
<p> </p>
<p><span>难道是句代码可以注册多个代理?</span></p>
<p><span>t = (T) pb.bind(t, pb, methods[i].getName());<br></span></p>
<p> </p>
<p> </p>
<p> </p>
</div>
<p>请认真看invoke方法</p>
</div>
<p> </p>
<p>哦,有递归...</p>
3 楼 Cindy_Lee 2011-03-15  
<div class="quote_title">t42dw 写道</div>
<div class="quote_div">
<p><span>
</span></p>
<div class="quote_div">我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass </div>
<p> </p>
<p><span>demo.sayHello();   </span></p>
<p><span>        System.out.println(</span><span class="string">"-----------------------------"</span><span>);   </span></p>
<p><span>        demo.sayHello2();   </span></p>
<p> </p>
<p><span>难道是句代码可以注册多个代理?</span></p>
<p><span>t = (T) pb.bind(t, pb, methods[i].getName());<br></span></p>
<p> </p>
<p> </p>
<p> </p>
</div>
<p>请认真看invoke方法</p>
2 楼 t42dw 2011-03-15  
<p><span>
<div class="quote_div">我不明白为啥demo可以使用两次,也就是调用两次方法?准确的说就是为啥两次调用可以区分是用那个ProxyClass </div>
</span></p>
<p><span>demo.sayHello();   </span></p>
<p><span>        System.out.println(</span><span class="string">"-----------------------------"</span><span>);   </span></p>
<p><span>        demo.sayHello2();   </span></p>
<p> </p>
<p><span>难道是句代码可以注册多个代理?</span></p>
<p><span>t = (T) pb.bind(t, pb, methods[i].getName());<br></span></p>
<p> </p>
<p> </p>
<p> </p>
1 楼 dwbin 2011-03-15  
不错,把异常再抛出来,ProxyBean里面的before和after可以设计成接口注入到某个容器里面,再有一个applicationcontext的概念我觉得就蛮好了

相关推荐

    Java 注解+动态代理的一个实例

    学习下动态代理模式(关于代理的基础只是有很多帖子都有我就不重复了),做了个注解动态代理的例子, 给那些学习注解或动态代理的初学者。

    spring.doc

    4.1.3 Spring的动态代理 71 4.2 AOP编程 71 4.2.1概念: 71 SpringAOP概念拓展: 73 之前实现了目标方法的动态调用,现在来实现切面的动态调用。 74 4.2.2 AOP实现的两种模式 78 4.2.2.1 xml形式 78 XML形式拓展: ...

    python爬虫整理

    自己学习爬虫的时候写的每一个例子,每个例子里面都有自己的注释和解析,总共大概有几十个例子,包括百度贴吧,糗事百科,音乐,图片,代理等等很多内容,因为上传的文件大小有限制,所以删减了部分,大部分都是可以...

    Java EE常用框架.xmind

    shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权 传统使用URL拦截的时候,要将所有的URL都配置起来,繁琐、不易维护 而我们的Shiro实现系统的权限管理,有效提高开发效率,从而...

    Spring面试题含答案.pdf

    35. 你可以在 Spring 中注入一个 null 和一个空字符串吗? 36. 什么是基于 Java 的 Spring 注解配置? 给一些注解的例子 37. 什么是基于注解的容器配置? 38. 怎样开启注解装配? 39. @Required 注解 40. @Autowired ...

    JSP基于SSM公司商品进销存系统源码

    应用程序是一个电子供应商,既经营网站又经营许多实体商店。例子包括百思买和电路城。要想了解更多关于这个应用程序的信息,请考虑一下你可能在网上和商店购买的任何经验,并浏览他们的网站。 技术要点: 1、此系统...

    springCloud

    下面是一个配置中心刷新配置的例子 1、提交代码触发post请求给bus/refresh 2、server端接收到请求并发送给Spring Cloud Bus 3、Spring Cloud bus接到消息并通知给其它客户端 4、其它客户端接收到通知,请求Server...

    Spring.3.x企业应用开发实战(完整版).part2

    7.3.2 一个简单的例子 7.3.3 如何通过配置使用@AspectJ切面 7.4 @AspectJ语法基础 7.4.1 切点表达式函数 7.4.2 在函数入参中使用通配符 7.4.3 逻辑运算符 7.4.4 不同增强类型 7.4.5 引介增强用法 7.5 切点函数详解 ...

    Spring3.x企业应用开发实战(完整版) part1

    7.3.2 一个简单的例子 7.3.3 如何通过配置使用@AspectJ切面 7.4 @AspectJ语法基础 7.4.1 切点表达式函数 7.4.2 在函数入参中使用通配符 7.4.3 逻辑运算符 7.4.4 不同增强类型 7.4.5 引介增强用法 7.5 切点函数详解 ...

    Ruby类继承、抽象类、类拓展混入、代理类实例

    总结一下工作中遇到的类扩展: 1、类继承: 当多个类公用很多方法的时候可以将公用方法部分抽取出来,需要的类做相关继承。...(引用一个别人的注解来描述抽象类的运用吧https://ihower.tw/rails4/

    Hibernate+中文文档

    4.1. 一个简单的POJO例子 4.1.1. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.2. 提供一个标识属性(identifier property)(可选) 4.1.3. 使用非final的类 (可选) 4.1.4. 为持久化字段声明访问...

    Spring中文帮助文档

    9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @...

    spring.net中文手册在线版

    14.5.2.第一个例子 14.5.3.Transaction特性的设置 14.5.4.通过AutoProxyCreator使用声明式事务 14.5.5.通过TransactionProxyFactoryObject使用声明式事务 14.5.6. 通过ProxyFactoryObject使用声明式事务 14.5.7. ...

    Spring API

    9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @...

    word源码java-practice:这个项目是记录自己平常的一些练习

    根据链接得到股票数据,多个线程同时运行获取股票数据,获取到一定量后再写入文件中(做这个的目的,主要是为了看看当获取到数据很多时候,应该怎么处理文件和用这个文件来做一些大数据查找相关题目的练习) ...

    Hibernate3+中文参考文档

    4.1. 一个简单的POJO例子 4.1.1. 为持久化字段声明访问器(accessors)和是否可变的标志(mutators) 4.1.2. 实现一个默认的(即无参数的)构造方法(constructor) 4.1.3. 提供一个标识属性(identifier property)(可...

    双鱼林JSP商品进销存系统 v1.0

    集团可以通过产品(相机,电话等),制造商(索尼,苹果等),或通过其他手段(例如,网关PC可能与索尼显示器和惠普打印机打包,并作为一个软件包销售)。 一些客户与公司签订合同,并将他们的购买记在账户号码上。...

    JBoss Seam 工作原理、seam和hibernate的范例、RESTFul的seam、seam-gen起步、seam组件、配置组件、jsf,jboss、标签、PDF、注解等等

    1.2. 第一个例子:注册示例.............................................................................................................................................. 15 1.2.1. 了解代码.................

    Spring 2.0 开发参考手册

    9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. 结合AspectJ使用 @Transactional 9.6. 编程...

Global site tag (gtag.js) - Google Analytics