我想你还是不太明白动态代理的原理,这样吧,我把我以前写的一个博客给你拿过来吧,希望能帮到你。
博客地址是:http://blog.csdn.net/dreamskyforjava/article/details/9672131
JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。而Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例。下面我就用一个实例演示面向切面编程中动态代理的过程。
首先把需要的类引入进来
User类- public class User {
-
- private String userName;
- private String password;
-
- public String getUserName() {
- return userName;
- }
- public void setUserName(String userName) {
- this.userName = userName;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
-
- }</span>
- 接口UserDao:
- [java] view plaincopyprint?
- <span style="font-family:Times New Roman;"><span style="font-size:18px;">package com.spring.dao;
-
- import com.spring.model.User;
-
- public interface UserDao {
-
- public void save(User u);
-
- public void delete();
- }</span>
- </span>
- UserDaoImpl:
- [java] view plaincopyprint?
- <span style="font-family:Times New Roman;font-size:18px;">package com.spring.dao.impl;
-
- import com.spring.dao.UserDao;
- import com.spring.model.User;
-
- public class UserDaoImpl implements UserDao{
-
- public void save(User u) {
-
- System.out.println("user saved !");
- }
-
- public void delete()
- {
- System.out.println("delete ok !");
- }
-
- }
复制代码 好了,下面我们要做的事就是写出一个UserDaoImpl类的动态代理类,这个代理类实现的功能是在调用UserDaoImpl类方法的时候提示该方法已经开始执行的语句。代理类LogInterceptor,他实现了InvocationHandler接口- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
-
- public class LogInterceptor implements InvocationHandler {
-
- private Object target; //接收被代理类的对象
-
- public Object getTarget() {
- return target;
- }
-
- public void setTarget(Object target) {
- this.target = target;
- }
-
- public void beforeMethod(Method m)
- {
- System.out.println(m.getName()+" start !");
- }
-
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {</span><span style="font-family:Times New Roman;">
- <span style="font-size:14px;">beforeMethod(method);
- method.invoke(target, args);
- return null;</span>
- }
- }
复制代码 在接口方法invoke(Object proxy, Methodmethod, Object[] args)里,将目标类实例传给method.invoke()方法,通过反射调用目标类方法。最后就是生成代理类对象并初始化,调用方法查看结果,完成切面编程的过程。以junit进行单元测试,代码如下
public void taestProxy()
{
UserDao userDao = new UserDaoImpl();
LogInterceptor li = new LogInterceptor();
li.setTarget(userDao);
//为编织了目标业务类逻辑和横切逻辑的LogInterceptor创建代理类
UserDao proxy = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), li);</span><span style="font-family:Times New Roman;font-size:18px;">
proxy.save(new User());
proxy.delete();
}
上面的代码完成了业务类代码和横切代码编织和接口代理实例生成的工作,其中在li.setTarget(userDao)处,我们将LogInterceptor实例编织为一个包含业务逻辑和横切逻辑实例,然后在newProxyInstance处,通过Proxy的静态方法newProxyInstance()为融合了业务类逻辑和横切逻辑的LogInterceptor创建一个UserDao接口的代理实例,该方法的第一个入参为类加载器,第二个入参为创建的代理实例所要实现的一组接口,第三个参数是整合了业务逻辑和横切逻辑的编织器对象。简言之这三个参数分别是UserDaoImpl的类加载器、UserDao接口、实现了代理的类LogInterceptor对象,此时UserDaoImpl是被代理的对象
|