比如我们在给数据库新增数据时,没有使用代理之前,在我们操作每个方法之前都需要去打开数据库连接,方法执行完成后去关闭数据库,这是一件重复而费时的工作.
public interface UserService{
public void save();
}
public class UserServiceImpl implements UserService{
@Autowired
public void save(){
System.out.println("连接数据库");
System.out.println("新增数据");
System.out.println("关闭数据库");
}
}
静态代理
为了简化重复的工作,我们使用静态代理进行操作数据库.方法内只做,方法需要做的操作.其他的交给代理.
优点:
业务只需要关注业务逻辑本身,保证了业务类的重用性.
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
public interface UserService{
public void save();
}
public class UserService implements UserService{
@Autowired
public void save(){
System.out.println("新增数据");
}
}
/**
*代理类
*/
public class UserServiceProxy implements UserService{
private UserService userService;
public UserServiceProxy(UserServieImpl userServie) {
this.userService = userServie;
}
public void open(){
System.out.println("打开数据库");
}
public void close(){
System.out.println("关闭数据库");
}
@Autowired
public void save(){
open();
userService.save();
close();
}
}
public class Test{
public static void main(String[] args){
UserService userService = new UserServiceProxy(new UserServiceImpl());
userService.save();
}
}
动态代理
动态代理优点:
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强
public 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);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
open();
Object result=method.invoke(target, args);//通过反射调用真实业务对象的业务方法,并且返回
close();
return result;
}
public void open(){
System.out.println("打开数据库连接");
}
public void close(){
System.out.println("关闭数据库连接");
}
}