`
Cindy_Lee
  • 浏览: 112257 次
  • 性别: 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 注解+动态代理的一个实例

    本文将通过一个具体的例子来展示如何结合使用注解和动态代理技术。 #### 二、关键概念解析 ##### 1. **动态代理** - **定义**:动态代理是指在运行时动态创建代理对象的过程。这种机制可以用来为任何接口类型的...

    动态代理(AOP)简单例子

    动态代理(Aspect-Oriented Programming,AOP)是面向切面编程的一种编程范式,它主要用来解决传统面向对象编程中难以处理的横切关注...这个例子对于初学者来说是一个很好的实践,有助于深入理解AOP和动态代理的概念。

    spring动态代理类的示范小版本,很简单的例子

    这个"spring动态代理类的示范小版本,很简单的例子"应该是提供了一个简单易懂的示例,帮助我们理解Spring动态代理的工作原理。 在Spring中,动态代理主要有两种实现方式:JDK动态代理和CGLIB代理。它们都是为了实现...

    动态代理加注解实现细粒度的权限管理,具体到方法

    动态代理是在运行时创建一个接口的实现类,该实现类能够调用实际的目标对象(被代理对象)的方法。Java中,我们可以使用`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现动态代理。...

    springboot中的 动态代理的选择测试代码

    另外,CGLIB是一个强大的高性能的代码生成库,它可以用来扩展Java类与实现Java接口,并且提供了一个API来动态地创建代理对象。 在Spring Boot中,AOP(面向切面编程)是通过动态代理实现的,用于解耦核心业务逻辑和...

    Java动态代理自建注解

    接下来,我们需要创建一个动态代理类来处理注解。Java的`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口提供了实现动态代理的基础设施。`InvocationHandler`接口定义了一个`invoke`方法,...

    spring+blazeDS+flex4 例子

    在“spring+blazeDS+flex4 例子”项目中,我们看到一个完整的集成示例。该项目可以直接运行,所有必要的jar包都已包含。首先,我们需要在Spring配置中定义BlazeDS的通道配置和服务接口。然后,在Flex4的MXML或AS3...

    spring之AOP(动态代理)

    在这个例子中,`@Around`注解定义了一个环绕通知,它将在匹配方法执行之前和之后运行。`execution(* com.example.service.*.*(..))`是一个切入点表达式,用于定义要拦截的方法。 最后,Spring会自动扫描并应用所有...

    Spring+SpringMVC+Mybatis框架整合例子(SSM)

    4. **整合Mybatis与Spring**:将Mybatis的SqlSessionFactoryBean定义在Spring配置中,实现DAO接口,并使用Spring的代理机制实现接口的动态代理。 5. **编写Mapper接口和XML映射文件**:定义SQL操作接口,对应的XML...

    SpringAOP之探秘(动态代理、责任链模式、注解使用)

    JDK动态代理基于接口,当目标类实现了至少一个接口时,Java会生成一个代理类来执行增强的代码。而CGLIB则是在运行时通过字节码技术生成一个子类,用于实现对非接口类的代理。CGLIB通常作为Spring AOP的默认代理机制...

    Spring 动态代理和aop切面编程例子

    在这个例子中,`@Transactional`注解告诉Spring在`addUser`方法的执行过程中开启和提交一个数据库事务。如果方法抛出异常,事务将被回滚,保证了数据的一致性。 总结来说,Spring的动态代理和AOP是强大的工具,它们...

    动态代理加注解实现细粒度的权限管理,具体到方法(前面上传的资源修改)

    动态代理可以在运行时创建一个实现了特定接口的新类,这个新类会在调用每个接口方法时执行额外的逻辑,如日志记录、事务管理或者——就像在这个例子中——权限检查。当我们无法提前知道所有可能的代理类,或者需要在...

    spingmvc+spring+mybatis框架搭建的例子,适合初学者

    7. **实战应用**:这个例子适合初学者,因为它提供了一个实际的项目结构,让学习者能够了解如何将这三个框架集成并应用于实际项目。通过这个实例,开发者可以学习到如何搭建基本的服务,然后在此基础上添加自己的...

    反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) - Java 例子 -

    Spring框架是Java中实现AOP的一个流行工具,它通过动态代理机制实现了这一功能。本文将深入探讨Spring AOP的实现原理,以及如何使用反射来实现动态代理模式。 首先,我们需要了解AOP的基本概念。AOP的核心思想是切...

    Spring的注解,带一小例子

    了解了这些基本注解后,我们可以通过一个小例子来实践。假设我们有一个简单的服务类`UserService`,它依赖于`UserRepository`来操作用户数据: ```java @Service public class UserService { @Autowired private ...

    MyBatis注解配置映射器:动态SQL的实现

    下面以一个具体的例子来说明如何使用注解和动态SQL: 假设我们有一个`User`实体类,包含`id`、`name`和`age`属性。我们想要编写一个查询用户的方法,根据用户的名字或年龄筛选结果。可以创建一个名为`UserMapper`的...

    Spring AOP与动态代理

    动态代理避免了对原始类字节码的修改,而是在运行时动态创建一个与目标类具有相同方法的新对象,这个新对象会在调用目标方法前后执行额外的逻辑。Spring AOP提供了两种动态代理方式:JDK动态代理和CGLIB动态代理。 ...

    mybatis如何实现注解sql的简单例子

    在上面的代码中,`getMapper()`方法会根据传入的接口类型返回一个实现了该接口的代理对象,这个代理对象能够处理我们之前在接口方法上定义的注解。 在实际项目中,我们可能需要处理更复杂的SQL,比如更新、删除等...

    SpringAOP注解特棒例子

    1. `@Aspect`:这个注解用于标记一个类作为切面。切面类通常包含一系列的通知方法(advice),这些方法会在特定的连接点(join point)执行。 2. `@Before`:这个注解表示前置通知,也就是在目标方法执行之前执行的...

Global site tag (gtag.js) - Google Analytics