终于到了总结spring的入门了,ssh这三个框架中,spring是理解的最浅的,也是最需要话功夫研究了,今天只搞了一点点,不过也要记录下来。
先看看用jdk,怎样实现动态代理,首先我们需要使用Proxy,Proxy是专门用来完成代理操作的类,可以通过此类为一个或者多个接口动态的生成实现类,具体调用的方法为:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws illegalArgumentException
通过newProxyInstance()方法可以动态的生成实现类,该方法有三个参数:
1,ClassLoader loader :类加载器
2,Class<?>[] interfaces: 得到被代理类的全部接口
3,InvocationHandler h: 得到InvocationHandler 接口的子类实现类(通常我们需要加入的逻辑,就是在InvocationHandler的子类中来实现)
显然要使用动态代理就必须实现InvocationHandler的接口,InvocationHandler的定义中有一个invoke的抽象方法:
pubic Object invoke(Object Proxy,Method method,Object[] args该方法也有三个参数,分别如下:
1, Object proxy 表示被代理的对象
2, Method method 表示被代理类需要执行的方法
3, Object[] args 表示执行方法所需要的参数
为了演示动态代理的过程首先需要设计一个接口:userDaoinf 里面有两个方法,一个添加用户,一个删除用户
package edu.hue.jk.aop;
public interface userDaoInf {
public void addUser(); // 添加用户
public void deleteUser();// 删除用户
}
然后给出它的实现类,UserDao:
package edu.hue.jk.aop;
public class UserDao implements userDaoInf {
public void addUser() {
System.out.println("add user successful");
}
public void deleteUser() {
System.out.println("delete user successful");
}
}
实现InvocationHandler接口,MyInvocationHandler:在实现该接口的时候,根据不同的调用方法可以选择执行不同的逻辑:
package edu.hue.jk.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object object; // 被代理的类
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public void beforeMethod(){
System.out.println("您拥有权限");
}
public Object invoke(Object proxy, Method method, Object[] args) //使用invoke方法来动态的调用被代理类的方法
throws Throwable {
if(method.getName().equals("deleteUser")) // 根据不同的方法执行不同的逻辑,如果是deleteUser方法,则先执行beforeMethod()
{
beforeMethod();
//System.out.println("methodName:"+method.getName());
Object tem=method.invoke(this.object, args);
return tem;
}
else {
Object tem=method.invoke(this.object, args);
return tem;
}
}
}
结果测试:<pre name="code" class="java">package edu.hue.jk.aop;
import java.lang.reflect.Proxy;
public class AopTest {
public static void main(String[] args) {
userDaoInf userDao=new UserDao(); // 生成代理类的目标对象
MyInvocationHandler handler=new MyInvocationHandler(); // 需要织入的代码
handler.setObject(userDao); // 动态的调用userDao的方法
// Class<?>[] inters= userDao.getClass().getInterfaces();
// for(Class<?> o:inters) // 打印所有的接口
// System.out.println("interfaces :"+o.getName());
//为userDao生成代理对象
userDaoInf uproxy=(userDaoInf)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), handler);
// 使用代理对象来完成操作
uproxy.addUser();
uproxy.deleteUser();
System.out.println(uproxy.getClass().getName()); // 打印生成的代理类的名字
}
}
运行程序: 最后只在deleteUser()时候加入了 我们自己的逻辑
add user successful
您拥有权限
delete user successful
$Proxy0
上面的程序实现了动态的代理的原理,那么spring的封装给我们带来了方便没有呢,同样的逻辑,我用spring实现如下:
定义一个UserService 的接口:
package edu.hue.jk.aop;
public interface UserService {
public void addUser();
public void deleteUser();
}
实现接口:
package edu.hue.jk.aop;
import org.springframework.stereotype.Component;
@Component("userService")
public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("add User successful");
}
public void deleteUser() {
System.out.println("delete user successful");
}
}
配置切面aspect :
package edu.hue.jk.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component("loginter")
public class Loginter {
@Before("execution(* edu.hue.jk.aop.UserServiceImpl.*())") //在执行UserServiceImpl的所有方法之前先调用beforeMethod()的逻辑
public void beforeMethod(){
System.out.println("您拥有权限:");
}
}
程序的测试代码:
package edu.hue.jk.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopTestMain {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service=(UserService)context.getBean("userService",UserService.class);
service.addUser();
service.deleteUser();
}
}
最后结果:
您拥有权限:
add User successful
您拥有权限:
delete user successful
可见在执行两个方法都加入了自己添加的逻辑,也可以根据配置@before annotation 来修改。可见使用spring 配置切面来实现动态代理相比之下要简单的多,不用自己去实现InvocationHandler 接口。