Spring动态代理
今天是学习Spring的第二天,看到了AOP,即AspectOrientedProgramming 面向切面编程,
JDK 的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中 InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一 起。而Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例。下面我就用一个实例演示面向切面编程中动态代理的过 程。
首先把需要的类引入进来
User类:
package com.spring.model;
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;
}
}
接口UserDao:
package com.spring.dao;
import com.spring.model.User;
public interface UserDao {
public void save(User u);
public void delete();
}
UserDaoImpl:
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接口
package com.spring.aop; 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 { beforeMethod(method); method.invoke(target, args); return null; } }
在接口方法 invoke(Object proxy, Methodmethod, Object[] args)里,将目标类实例传给method.invoke()方法,通过反射调用目标类方法。最后就是生成代理类对象并初始化,调用方法查看结果,完成 切面编程的过程。以junit进行单元测试,代码如下
@Test 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); proxy.save(new User()); proxy.delete(); }
上 面的代码完成了业务类代码和横切代码编织和接口代理实例生成的工作,其中在li.setTarget(userDao)处,我们将 LogInterceptor实例编织为一个包含业务逻辑和横切逻辑实例,然后在newProxyInstance处,通过Proxy的静态方法 newProxyInstance()为融合了业务类逻辑和横切逻辑的LogInterceptor创建一个UserDao接口的代理实例,该方法的第一 个入参为类加载器,第二个入参为创建的代理实例所要实现的一组接口,第三个参数是整合了业务逻辑和横切逻辑的编织器对象。简言之这三个参数分别是 UserDaoImpl的类加载器、UserDao接口、实现了代理的类LogInterceptor对象,此时UserDaoImpl是被代理的对象
运行结果如下
浙公网安备 33010602011771号