动态代理-Java中动态代理的使用
需求和概念
1.需求:
当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强
2.动态代理实现
首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最后返回
应用:Spring的AOP,加事务,加权限,加日志
类说明
//被代理类的接口
com.blue.service.UserService
//被代理实现类
com.blue.service.impl.UserServiceImpl
//自定义的代理实现类
com.blue.service.handle.CustomInvocationHandler
//jdk动态代理工具类,如果想看具体实现,请参考源码
java.lang.reflect.Proxy
//代理测试类,测试效果用的
com.blue.TestProxy
具体实现
UserService:
public interface UserService {
public void save(String user,String password);
public void delete(String id);
}
UserServiceImpl:
public class UserServiceImpl implements UserService {
@Override
public void save(String user,String password) {
System.out.println("存储用户信息("+user+","+password+")");
}
@Override
public void delete(String id) {
System.out.println("删除用户:"+id);
}
}
CustomInvocationHandler:
public class CustomInvocationHandler implements InvocationHandler {
private UserService userService;
public CustomInvocationHandler(UserService userService){
this.userService = userService;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用前拦截");
Object obj = method.invoke(userService,args);
System.out.println("调用后收尾");
return obj;
}
}
这里InvocationHandler
是jdk自带的基础接口
TestProxy:
public class TestProxy {
/**
* 动态代理使用
*/
@Test
public void testProxy(){
/*
动态代理所需条件
1.代理类(CustomInvocationHandler)
2.被代理的对象(UserServiceImpl)
3.被代理对象的接口列表(UserService)
4.代理工具类(Proxy)
*/
UserService service = new UserServiceImpl();
service = (UserService)Proxy.newProxyInstance(CustomInvocationHandler.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),new CustomInvocationHandler(service));
System.out.println("调用UserServiceImpl的save方法:");
service.save("zhangsan","123456");
System.out.println();
System.out.println("调用UserServiceImpl的delete方法:");
service.delete("kevin");
}
}