一、动态代理简介
动态代理与普通代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每个方法进行中转。
动态代理类只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。该方法就是调用被代理接口的所有方法时需要调用的,而invoke方法返回的值是被代理接口的一个实现类。
二、实例解析
接口:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring; public interface IUser { public void addUser(String strName); } </span>
实现类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring; public class User implements IUser { @Override public void addUser(String strName) { System.out.println("姓名是:"+strName); } } </span>动态代理类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class IsSuccessHandler implements InvocationHandler { private Object targetObject; public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //调用目标方法 Object ret = method.invoke(targetObject, args); check(); return ret; } private void check() { System.out.println("-------Angel,you are successful-------"); } } </span>
application配置文件:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id="user" class="com.angel.spring.User"/> <bean id="userProxy" class="com.angel.spring.IsSuccessHandler"/> </beans> </span>
测试类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.spring; import org.springframework.beans.factory.BeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import junit.framework.TestCase; public class TestUser extends TestCase { public void testAdd() { // 读取配置文件 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); IsSuccessHandler handler=(IsSuccessHandler)factory.getBean("userProxy"); User user=(User)factory.getBean("user"); IUser iUser=(IUser)handler.createProxyInstance(user); iUser.addUser("Andy+Angel"); } }</span>
三、总结
在使用静态代理的时候,当我们的接口增加了一个方法,那么实现类和代理类都必须同时增加一个方法的实现,而且在代理类里面,还必须为每个方法加上拦截处理。在少量类的时候,这样子的处理并没有什么不妥。但是一旦系统复杂点,类变得比较多的时候,静态代理的弊端显露无疑。采用动态代理,事先并没有为实现类创建代理,只有当调用方法时才动态的创建一个代理。
把一些外加的事务采用动态代理进行处理,这样子,实现类就可以只关注自己的职责了,分工明确,perfect!