8
回答
关于一段JAVA代码的理解(Spring)
注册华为云得mate10,2.9折抢先购!>>>   
DataCenterService dataCenterService = LocalSpringContext
		    .getBean(DataCenterService.class);

DataCenterService是一个接口,规定了一些对数据库的操作函数。

类LocalSpringContext继承ApplicationContextAware 。

刚学习Java和相关框架,这段不太懂..

1. 接口也能有对象吗? 一般这么写有什么用?

2. 接口的.class获得的是什么对象,难道是继承了该接口,具体实现了其中方法的类的对象?

3. getBean方法调用ApplicationContextAware里的方法,可这是个接口啊,这么写会跳转到其具体实现吗?

public class LocalSpringContext implements ApplicationContextAware {
	private static ApplicationContext springCtx;

	public void setApplicationContext(ApplicationContext context)
			throws BeansException {
		springCtx = context;
	}
	/**
	 * 按类型获取BEAN
	 * @param clazz
	 * @return
	 */
	public static <T> T getBean(Class<T> clazz){
		
		return springCtx.getBean(clazz);
	}

   新手不太明白,请大家多关照

举报
Aww
发帖于3年前 8回/688阅
共有8个答案 最后回答: 3年前

1、用处在于任何位置静态方法都可以得到 ApplicationContext (Spring 要先启动),从而得到 Bean

2、.getBean(clazz)是按类查找 Bean 的方式,会自动找到对应实现

3、虽然没写,但我猜想 LocalSpringConext 应该也是配到了 Spring 环境中了,Spring 加载 Bean 是会扫描 Spring 自有的一些接口,并操作。如:Aware,Spring 加载这个 Bean 时,发现了这个接口,就是将 ApplicationContext 注入(setApplicationContext)

对象实现了接口,那么接口可以定义对象,举个例子:小明这个对象实现了人这个接口,那么:

人 r=new 小明();

小明是人,所以可以这么创建对象;

同样也可以:

人 r=new 小红();

因为都实现了人这个接口,这样的话人不局限于实实在在某个人,这样就解耦了



1、接口不能实例化对象。

刚学Java会觉得莫名其妙,因为随处都可以看到类似下面的代码:

接口 obj = new 接口Impl();

以为这里是用接口实例化对象,其实是错的。这行代码实际做了两件事:声明和赋值。声明是说对象obj是一个接口类型的对象,赋值是说obj被赋予一个接口具体实现的对象。接口就像模具,它是一个空壳子,可能有各种不同材质的产品实现,但是你没办法把模具当成真正的产品来用。如果把接口类比成“生物”,你就可以这样:

生物 person = new 人();
生物 animal = new 动物();
生物 plant = new 植物();

你说person、animal以及plant都是生物,这是没问题。但是生物是一个模糊的概念,没有具体的实物与之对应,所以我们在赋值的时候,需要new具体的实现类,也就是人、动物或是植物。

2、接口为什么不能实例化对象?

这个问题在中文网站搜索根本找不到答案,因为几乎没有关心或者大家都心知肚明。之所以接口不能实例化一个对象,是因为接口根本没有具体的实现,它只规定了实现该接口的类有哪些行为,但这些行为如何做,没有说。拿上面的例子来说,我们都知道只要是生物都可以吸收营养,但是人、动物还有植物吸收营养的具体过程是各不相同的。如果我说这是一个生物(即声明对象:生物 unknow = new 生物()),当我要求它吸收营养时,它该怎么做呢?转化成代码如下:

public interface 生物{
    @Override
    public void 吸收营养();
}

可以看的出,处于接口生物下的吸收营养方法,没有具体的实现,只是一个方法声明。那么如下代码有什么用呢?

生物 unknown = new 生物();
unknow.吸收营养();    // 这里到底是怎么吸收营养的?这个生物该做什么?

即便发出了让生物吸收营养的指令,生物也准备吸收营养,但真的去吸收营养时,却发现不知道该做什么。这就是接口实例化对象的接口,一个没有任何实现的对象,无论你对它做什么操作,它都会感到手足无措。

3、接口有什么用?

接口的意义就如之前提到的模具一样它给各种实现类提供了一个规范,它告诉使用者实现该接口的类大概长成什么样子,可以做什么事,只是它不关心具体怎么做而已。与其说是接口,不如通俗说它是一个总称。就好像我说你给我画一个多边形,你画三角形、四边形、五边形、六边形......都是对的,多边形是总称(接口),N变形是具体实现。但如果你不自动脑补,你根本不知道多边形该怎么画,因为你不知道多边形到底有几条边。

还以生物为例,何为生物,人、动物、植物这些都是生物,当然还有其它生物,就好比还有一边形(圆),只有当我们需要时,我们才会去提出它。下面就是几个对生物接口的具体实现类:

class 人 implements 生物{
    @Override
    public void 吸收营养(){
        System.out.println("吃饭");
    }
}

class 动物 implements 生物{
    @Override
    public void 吸收营养(){
        System.out.println("吃食");
    }
}

class 植物 implements 生物{
    @Override
    public void 吸收营养(){
        System.out.println("光合作用");
    }
}

现在接口有用了,它可以让几个具体实现类产生某种关系:它们可以统称为生物。但这还有没体现出接口实用之处,因为我们还没有实现这些具体类。

假设你被要求养一种生物,但这个生物前期是不明确的,你不知道它是人,是动物,还是植物。但是你不必紧张,因为你知道,无论它具体是什么,只要是生物,它都有吸收营养的能力,那你就不怕养不活它。所以,你可能面临的是这样的情况:

public class 喂养者 extends 人{
    public 喂养者(){
        // 你是一个人,同样也是一个生物,你也可以吸收营养,吃饱了才有力气干活
        this.吸收营养();
    }
    
    /**
     * 喂养对象声明成接口类型,就可以接收任意实现该接口的类对象作为参数
     * 如果不这样,有可能你就需要三个方法:喂养人、喂养动物、喂养植物
     */
    public void 喂养(生物 baby){
        baby.吸收营养(); // 这里是调用接口的方法吗?不是,这个方法是实参对象的方法!
    }
}

看,喂养方法似乎在说:我不知道你将交给我一个什么样的生物,但我知道,喂养它,就是让它吸收营养。接下来你就可以喂养你接手的生物了:

public class 生物喂养室{
    public static void main(String[] args){
        // 你来当喂养者吧
        喂养者 you = new 喂养者();
        
        // 这里有一个小孩
        生物 baby = new 人();
        // 喂养它吧
        you.喂养(baby);
        
        // 又有一只小动物要让你来喂养了
        生物 cat = new 动物();
        // 再不喂养,它可就要饿坏了
        you.喂养(cat);
        
        // 还有一盆花,给你的小屋增添不少生机
        生物 flower = new 植物();
        // 但你不能让它死了
        you.喂养(flower);
        
        // 累了吗,犒劳一下自己吧
        you.喂养(you);
    }
}

上面这些代码,既是接口的用处用法,又是接口使用场景。我的理解是,接口站在了更高的高度,它制定了一套流程,告诉别人哪一步应该做什么事,但具体怎么做,它不管你。所以我们可以看到,在java.sql包下,大部分都是接口,而具体的实现类,只有到用户使用的时候才会确定,是oracle、mysql还是db2。


--- 共有 1 条评论 ---
Aww谢谢,写的很容易理解。我的问题主要是因为,这次的代码并不是典型的 接口 itf = new impl(); 这次遇到的是 接口 itf =LocalSpringContext .getBean(DataCenterService.class); 开始我不知道.getBean会自动搜索并返回实现该接口的对象,还是对Spring的机制不理解,所以也没往多态这边想。。。 3年前 回复
顶部