很多人都有问过,为什么我们在刚刚学习ssh mvc的时候,是依赖接口注入而不是抽象类。要解答这个问题,我们需要了解接口和抽象类这两概念。
调用:
从此可以看出 JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
1.在java编程思想中,抽象类的定义是包含抽象方法的类。
public abstract class Bird {
}
抽象类有三点要注意:
1>抽象类不能用于创建对象。
2>抽象方法必须用public 或protected来修饰。如果为private就不能被子类所继承,所以抽象方法用private修饰是无法通过编译的。在默认情况下抽象方法是public。
3>如果子类无法实现所继承父类的抽象方法,则子类必须为抽象类。
2.接口,sun的设计初衷是对行为的抽象。
public interface Flyable {
Long flight_mile= 100l;
void fly();
}
接口特性:
1>接口中的变量都会被隐式地定义为public static final,方法会被隐式的定义为 public abstract。所以可以使用接口中的变量定义你的constant。
2>接口中所有成员必须为public。
3>抽象类实现接口,可以不用实现接口中的所有方法。
我们把抽象类和接口的特性拿出来比较了。下面我们再把抽象类和接口放在一起看看:
在宏观设计上:
1>抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部行为进行抽象。
2>抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计
语法层面上的区别:
1>抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2>抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3>接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4>一个类只能继承一个抽象类,而一个类却可以实现多个接口。
综上我们了解了什么是接口什么是抽象类。下面我就讨论下为什么我在 spring的注入时要依赖接口。spring的ioc的基本原理是本剧配置文件,生产代理对象并提供对象的方法调用。aop也是通过配置产生代理对象再进行方法编织生成方法链按顺执行,这个以后再讲。
我们先来看看什么是代理模式。
目标接口:
public interface FlyService {
public void fly();
}
接口实现:
public class FlyServiceImpl implements FlyService {
@Override
public void fly() {
System.out.println("飞吧,喜鹊!");
}
}
代理类:
public class FlyProxy implements FlyService{
FlyService service;
public FlyProxy(FlyService service) {
this.service = service;
}
public void fly() {
service.fly();
}
}
调用者:
public class BusinessCenter {
FlyService service;
public void travel(){
FlyServiceImpl impl = new FlyServiceImpl();
service= new FlyProxy(impl);
proxy.fly();
}
}
代理的好处是在解耦的同时,也可以在代理方法中添加自己对方法前后都处理比如:
public class FlyProxy implements FlyService{
FlyService service;
public FlyProxy(FlyService service) {
this.service = service;
}
public void fly() {
System.out.println("准备起飞.");
service.fly();
System.out.println("好,降落吧!");
}
}
这就是我们aop编程的原始想法。(后面再讲)
2.动态代理。
代理类:
public class DynamicProxy implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
result=method.invoke(target, args);
return result;
}
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
调用:
public class BusinessCenter {
FlyService service;
public void travel() {
FlyServiceImpl impl = new FlyServiceImpl();
DynamicProxy proxy = new DynamicProxy();
service = (FlyService) proxy.bind(impl);
service.fly();
}
}
从此可以看出 JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。