静态代理
静态代理只能服务于一种类型的对象,不利于业务的扩展
package com.tskpcp.proxy;
/**
*业务层接口,定义个save方法
*/
interface UserSerivce{
public void saveUser();
}
/**
*代理类
*/
class UserServiceProxy implements UserService{
private UserService userService;
public UserServiceProxy(UserServiec userService){
super();
this.userService=userService;
}
public void open(){
System.out.println("1:打开");
}
public void close(){
System.out.println("2:关闭");
}
@Override
public void saveUser(){
this.open();
userService.saveUser();
this.close();
}
}
/**
*业务层实现类,实现save方法
*/
class UserServiceImpl implements UserService{
@Override
public void saveUser(){
System.out.println("保存用户信息");
}
}
/**
*测试类
*/
public class TestProxy{
public static void main(String[] args){
UserService userService=new UserServiceProxy(new UserServiceImpl());
userService.saveUser();
}
}
动态代理
如果要实现动态代理,那么你要编写的那个代理类就需要实现一个InvocationHandle接口.这个接口所在位置是java.lang.reflect.InvocationHandler.看到reflect我们就能知道,动态代理肯定是通过反射来实现的了,这个接口中有一个方法:
Object invoke(Object proxy, Method method, Object[] args) :在代理实例上处理方法调用并返回结果。
invoke方法其实是反射里边的一个方法,在这个方法中有三个参数:
- Ojbect proxy:表示需要代理的对象
- Method method:表示要操作的方法
- Object[] args:method方法所需要传入的参数(可能没有为,null.也可能有多个)
如果要想让代理设计真正可用,我们还必须有一个代理类对象产生,这有用到了另一个类:java.lang.reflect.Proxy.
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
在这个类下面,我们找到了这样一个方法:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
该方法返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序.方法中有三个参数:
参数:
loader - 定义代理类的类加载器
interfaces - 代理类要实现的接口列表
h - 指派方法调用的调用处理程序
返回:
一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
package com.tskpcp.proxy;
/**
*业务层接口,定义个save方法
*/
interface UserSerivce{
public void saveUser();
}
/**
*代理类
*/
class UserServiceProxy implements UserService{
private UserService userService;
public UserServiceProxy(UserServiec userService){
super();
this.userService=userService;
}
public void open(){
System.out.println("1:打开");
}
public void close(){
System.out.println("2:关闭");
}
@Override
public void saveUser(){
this.open();
userService.saveUser();
this.close();
}
}
/**
*动态代理类
*/
class ServiceProxy implements InvocationHandler{
private Object target=null;//保存真实业务对象
/**
* 返回动态代理类的对象,这样用户才可以利用代理类对象去操作真实对象
* @param obj 包含有真实业务实现的对象
* @return 返回代理对象
*/
public Object getProxy(Object obj) {
this.target=obj;//保存真实业务对象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=method.invoke(target, args);//通过反射调用真实业务对象的业务方法,并且返回
return result;
}
}
/**
*业务层实现类,实现save方法
*/
class UserServiceImpl implements UserService{
@Override
public void saveUser(){
System.out.println("保存用户信息");
}
}
/**
*测试类
*/
public class TestProxy{
public static void main(String[] args){
UserService service=(UserService) new ServiceProxy().getProxy();
service.saveUser();
}
}
动态代理和静态代理相比较,最大的好处就是接口中声明的所有的方法都被转移到一个集中的方法中去处理,就是invocke()方法.这样在接口中声明的方法比较多的情况下我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
动态代理只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法的返回值是被代理接口的一个实现类。