面试题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.数据库创建索引

 

6.创建视图

 

上一篇:Spring包扫描机制详解


下一篇:Spring源码试读--BeanFactory模拟实现