/**
*模拟调用数据库
*/
public class UserDao {
private Map<String,String> users=new HashMap<String,String>();
public UserDao(){
users.put("bandaoti", "131310");
users.put("admin", "admin");
}
public voidcreate(String username,String password){
if(users.get(username)!=null) throw newRuntimeException("user exist!");
users.put(username,password);
}
public voidlogin(String username,String password){
String pw=users.get(username);
if(pw==null ||!pw.equals(password) )throw newRuntimeException("login failed!");
}
public void pring(){
System.out.println("UserList:");
Set<String> names=users.keySet();
for(Stringstr:names)System.out.println(str);
}
}
/**
* 用户服务接口
*/
public interfaceUserService {
void create(Stringusername,String password);
void login(Stringusername,String password);
}
/**
*用户接口和测试接口实例
*/
public classUserServiceImpl implements UserService ,TestInterface{
private UserDao userDao;
public voidsetUserDao(UserDao userDao) {
this.userDao =userDao;
}
@Override
public voidcreate(String username, String password) {
userDao.create(username,password);
}
@Override
public voidlogin(String username, String password) {
userDao.login(username,password);
}
@Override
public voidtestDoubleInterfaceInterCept() {
System.out.println("测试拦截两个接口的其中方法");
}
}
/**
*创建代理对象
*/
classMyAopProxy{
static Object createProxy(final Objectobj,final MethodBeforeAdvice methodBeforeAdvice){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),//代理类实现时的接口
newInvocationHandler() {
@Override
public Objectinvoke(Object proxy, Method method,
Object[] args) throws Throwable{
methodBeforeAdvice.before(method,args, obj);//先调用切面的before方法
returnmethod.invoke(obj, args);//嗲用对象的实际方法
}
});
}
}
public class test {
public static voidmain(String[] args) {
UserDao userDao = newUserDao();
UserServiceImpl userService = newUserServiceImpl();
userService.setUserDao(userDao);
MethodBeforeAdvice log = newMethodBeforeAdvice() {
@Override
public voidbefore(Method m, Object[] arg1, Object arg2)
throws Throwable{
System.out.println("Callmethod: " + m.getName());
}
};
UserService us=(UserService)MyAopProxy.createProxy(userService,log);
us.create("abcd", "123");
us.login("bandaoti", "131310");
TestInterfaceti=(TestInterface)MyAopProxy.createProxy(userService, log);
ti.testDoubleInterfaceInterCept();
}
}
接下来就要缕清思路了
首先是MyAopProxy类,其中有个方法为:createProxy,
最主要的就是Proxy.newProxyInstance这是实例一个代理对象,
第一个参数:类的装载器信息;第二个参数:对象的接口;第三个参数:(方法)拦截器,也就是说在执行代理对象前先执行这个拦截器(拦截器已经很普遍,不细述了)
然后中间什么Dao了,Impl了咱么都不细说了,此文章终点在于理解代理的执行过程
MethodBeforeAdvicelog = new MethodBeforeAdvice() {
@Override
public voidbefore(Method m, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("Callmethod: " + m.getName());
}
};
它就是我们在MyAopProxy;createProxy方法中拦截器调用那个before方法。在执行实际方法前先执行的before方法。
在测试方法中还有这么几句:
UserService us=(UserService)MyAopProxy.createProxy(userService,log);
us.create("abcd", "123");
us.login("bandaoti", "131310");
TestInterfaceti=(TestInterface)MyAopProxy.createProxy(userService, log);
ti.testDoubleInterfaceInterCept();
在执行us.create("abcd", "123");的时候,是调用的我们自己写的,生成代理对象的类,生成的对象中的create方法。它首先执行的是拦截器中调用before方法的代码行,然后再去执行实际方法。其中调用before的方法就是我们测试类中写的log对象中的方法。SO执行时在控制台会输出Call method: create
二次解释:
接下来解释代码中为什么有个测试接口(TestInterface),其实名字是我瞎起的并不合乎常理(但它确实是用来测试的)
在测试方法的最后我们有这么两句,
TestInterfaceti=(TestInterface)MyAopProxy.createProxy(userService, log);
ti.testDoubleInterfaceInterCept();
在仔细观察UserService类实现的接口后,发现它实现了两个接口,其中就有测试接口。原因是因为有这样的一个问题:(来自《Spring2.0核心技术与最佳实践》)其中UserService充当A接口,TestInterface充当B接口
到此,我基本把我所知道的都说出来了,虽然不够清晰。如果感觉无法忍受请立即摔碎电脑并双手不断拍胸脯大吼一声,NO~