面试题2

1.spring依赖注入的原理

链接:https://www.cnblogs.com/mthoutai/p/7278427.html

假设我们去看Spring的源代码可能涉及的类和接口相当多,不易掌握。在此我用自己的代码和方式来帮助我们Spring依赖注入的过程。 
当我们启动Spring容器的时候他会运行以下几个过程: 

(1、载入Xml配置文件(readXML(String filename))在Spring这个由ApplicationContext类完毕 
这一步会解析Xml属性。把bean的属性存放到BeanDefinition类中 
代码例如以下:

 1 /**
 2      * 读取xml配置文件
 3      * @param filename
 4      */
 5     private void readXML(String filename) {
 6            SAXReader saxReader = new SAXReader();   
 7             Document document=null;   
 8             try{
 9              URL xmlpath = this.getClass().getClassLoader().getResource(filename);
10              document = saxReader.read(xmlpath);
11              Map<String,String> nsMap = new HashMap<String,String>();
12              nsMap.put("ns","http://www.springframework.org/schema/beans");//加入命名空间
13              XPath xsub = document.createXPath("//ns:beans/ns:bean");//创建beans/bean查询路径
14              xsub.setNamespaceURIs(nsMap);//设置命名空间
15              List<Element> beans = xsub.selectNodes(document);//获取文档下全部bean节点 
16              for(Element element: beans){
17                 String id = element.attributeValue("id");//获取id属性值
18                 String clazz = element.attributeValue("class"); //获取class属性值        
19                 BeanDefinition beanDefine = new BeanDefinition(id, clazz);
20                 XPath propertysub =  element.createXPath("ns:property");
21                 propertysub.setNamespaceURIs(nsMap);//设置命名空间
22                 List<Element> propertys = propertysub.selectNodes(element);
23                 for(Element property : propertys){                  
24                     String propertyName = property.attributeValue("name");
25                     String propertyref = property.attributeValue("ref");
26                     PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyref);
27                     beanDefine.getPropertys().add(propertyDefinition);
28                 }
29                 beanDefines.add(beanDefine);
30              } 
31             }catch(Exception e){   
32                 e.printStackTrace();
33             }
34     }

2、Bean的实例化 
在配置文件以bean的id为key。BeanDefinition为value放到Map中

 1 /**
 2      * 完毕bean的实例化
 3      */
 4     private void instanceBeans() {
 5         for(BeanDefinition beanDefinition : beanDefines){
 6             try {
 7                 if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim()))
 8                     sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
 9             } catch (Exception e) {
10                 e.printStackTrace();
11             }
12         }
13 
14     }

3、为Bean的输入注入值。完毕依赖注入

 1 /**
 2      * 为bean对象的属性注入值
 3      */
 4     private void injectObject() {
 5         for(BeanDefinition beanDefinition : beanDefines){
 6             Object bean = sigletons.get(beanDefinition.getId());
 7             if(bean!=null){
 8                 try {
 9                     PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
10                     for(PropertyDefinition propertyDefinition : beanDefinition.getPropertys()){
11                         for(PropertyDescriptor properdesc : ps){
12                             if(propertyDefinition.getName().equals(properdesc.getName())){
13                                 Method setter = properdesc.getWriteMethod();//获取属性的setter方法 ,private
14                                 if(setter!=null){
15                                     Object value = sigletons.get(propertyDefinition.getRef());
16                                     setter.setAccessible(true);
17                                     setter.invoke(bean, value);//把引用对象注入到属性
18                                 }
19                                 break;
20                             }
21                         }
22                     }
23                 } catch (Exception e) {
24                 }
25             }
26         }
27     }

事实上Spring依赖注入的过程就是这么简单,再就是各种细节了。比方懒载入、单例等的额外处理了。

2.linux脚本

之前写过bash shell脚本 。略。

3.集群搭建

一般都是下载相关的包,解压,部署依赖环境,配置环境变量。略

4.常用spring注解

@Component

作用: 用于把当前类对象存入spring容器中

属性: value:用于指定bean的id。当我们不写时,它的默认值是当前类名,且首字母改小写

1 @Component
2 public class AccountDaoImpl implements IAccountDao {
3     public void saveAccount() {
4         System.out.println("保存了账户1111111111111");
5     }
6 }

在bean.xml中配置 

<context:component-scan base-package="com.itheima"></context:component-scan>

测试代码

1 public static void main(String[] args) {
2      ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
3      IAccountDao dao = ac.getBean("accountDaoImpl",IAccountDao.class);
4      System.out.println(dao);
5      dao.saveAccount();
6      ac.close();
7  }

由Component衍生而来的注解:

Controller:一般用在表现层

Service:   一般用在业务层

Repository:一般用在持久层

@Autowired

按照类型注入,有多个接口的实现会报错

自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功

如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错;

如果Ioc容器中有多个类型匹配时:先按照类型匹配,如果找到多个类型bean对象,再按照变量名作为bean的id去匹配,如果id不匹配,报错

Autowired出现位置: 可以是变量上,也可以是方法上

细节:在使用注解注入时,set方法就不是必须的了。

@Qualifier

用于注入数据的注解

但是在给方法参数注入时可以的

属性:value:用于指定注入bean的id

 

@Resource

作用:直接按照bean的id注入。它可以独立使用

属性:name:用于指定bean的id

注意: @Resource`是由JDK提供的注解,在JDK1.9之后移除到扩展模块之中.

所以如果想使用`@Resource`注解注入数据,请使用1.8及以下版本JDK

 

 

@Value

作用:用于注入基本类型和String类型的数据

属性:value:用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式)SpEL的写法:${表达式}

 

@Scope

指定bean的作用范围。

属性:

    value:指定范围的值。 取值:`singleton` `prototype` `request` `session` `globalsession`

5.数据库创建索引

 链接:https://blog.csdn.net/tomorrow_fine/article/details/78337735

 1 --创建一个普通索引
 2 create table index1 (
 3 id int, 
 4 name VARCHAR(20),
 5 sex boolean,
 6 INDEX(id)
 7 
 8 );
 9 --查看索引是否被使用
10 EXPLAIN SELECT * from index1 where id =1 ;
11 
12 --创建一个唯一性索引
13 create table index2(
14 id int unique,
15 name varchar(20),
16 unique index index2_id(id ASC)
17 );
18 --查看表结构
19 SHOW CREATE table index2
20 
21 --创建全文索引
22 create table index3(
23 id int,
24 info varchar(20),
25 FULLTEXT index index3_info(info)
26 
27 )ENGINE=MyISAM;
28 
29 SHOW CREATE table index3;
30 
31 --创建单列索引
32 CREATE TABLE index4(
33 id INT,
34 subject VARCHAR(30),    
35 INDEX index4_st(subject(10))
36 );
37 show create table index4;
38 
39 --创建多列索引
40 CREATE TABLE index5(id INT,
41 name VARCHAR(20),
42 sex CHAR(4),
43 INDEX index5_ns(name,sex)
44 
45 );
46 
47 --创建空间索引
48 CREATE TABLE index6(id INT,
49 space GEOMETRY NOT NULL,
50 SPATIAL INDEX index6_sp(space)
51 )ENGINE=MyISAM;

6.创建视图

链接:http://www.w3school.com.cn/sql/sql_view.asp

 创建视图语法:

1 CREATE VIEW view_name AS
2 SELECT column_name(s)
3 FROM table_name
4 WHERE condition

在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。

视图包含行和列,就像一个真实的表。视图中的字段就是来自一个或多个数据库中的真实的表中的字段。我们可以向视图添加 SQL 函数、WHERE 以及 JOIN 语句,我们也可以提交数据,就像这些来自于某个单一的表。

注释:数据库的设计和结构不会受到视图中的函数、where 或 join 语句的影响。

注释:视图总是显示最近的数据。每当用户查询视图时,数据库引擎通过使用 SQL 语句来重建数据。

7. 抽象类和接口的区别?

链接:https://www.cnblogs.com/yongjiapei/p/5494894.html

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。

2、抽象类要被子类继承,接口要被类实现。

3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果

7、抽象类里可以没有抽象方法

8、如果一个类里有抽象方法,那么这个类只能是抽象类

9、抽象方法要被实现,所以不能是静态的,也不能是私有的。

10、接口可继承接口,并可多继承接口,但类只能单根继承。

原文地址:https://www.cnblogs.com/battlecry/p/10397456.html