neweastsun 2019-10-29
Spring 框架:
前无古人,后无来者。它可以包容其他的一切框架。
a. 什么是Spring框架:
它是用于简化J2EE业务层开发的轻量级技术框架,他的核心是IOC和AOP
AOP:编程思想:面向对象: OOP
过程
服务: 分布式架构:SOA
切面的编程: AOP
b. 编码体验Spring 的强大之处:
作用:可以把普通的JavaBean魔术般的变为ejb
对象实例化的不同之处
c. 引入Spring框架
Spring.jar : spring1.0-Spring5.0 (屹立不倒,而且越来越牛)
d. 使用的Spring框架(容器)来构建对象:
观察:实例化武器Weapon 实例化骑士Knight
利用Spring框架来实例化这两个对象
配置 xml/annocation:以前Spring框架都是利用XML来配置
,但是现在来看还是标注。并存的,看的懂,其实用xml配置更加灵活
,清晰,但是他比较繁琐,而标注比较简单
beans.xml --- src/main/resources
e. 在配置文件中配置你需要实例化的JavaBean
Weapon Knight
f. 调用代码实例化Bean
原理: 工厂设计模式 反射机制
a.构建BeanFactory
ApplicationContext:其实就是那个工厂,他是创建Bean的工厂类
所以Spring框架利用了工厂设计模式,先构造出工厂类,然后工厂来实例化
他所管理的Bean。
b. 你要告诉这个工厂我要实例化哪些Bean传一个字符串来告诉工厂实例化的类
Spring把要实例化的Bean写到了配置文件中,
然后利用XML的解析技术拿到要实例化累的相关信息,然后实例化相应的Bean
c. 类只要能参数化了,那么就可以把他写道配置文件,
然后就可以利用反射技术进行实例化Class.forName("类名")
结论:Spring是个大容器(工厂) 他去实例化你想要的Bean,也就是说你把Bean的生命周期纳入到Spring容器中去管理,
不是我们直接构造出来的,这种技术就交Spring的IOC技术。
IOC技术: 控制反转,也叫(依赖注入),他们说的一回事。
控制反转:Bean的生命周期不受你控制,而是交给Spring容器管理。
优势: 1. 解耦,完全可以面向接口编程
在代码中完全不用体现具体的实现类
2. 类配置在配置文件中,方便修改维护
Spring容器对Bean的管理,默认是单例的。
Spring框架用到那些设计模式:工厂模式 单例模式 代理设计模式
Spring框架如何利用IOC
(1). 实现了控制反转,Spring容器能帮我们实例化对象,但是并没有做到DI(依赖注入)//为我们提供依赖注入。
配置Spring
xml来配置Bean,利用Spring容器来例化Bean(IOC)
Spring(4.0),Spring支持用标注的形式来配置
如何利用标注来实现Spring框架的IOC?
(1). 利用@Componet标注来注解你要纳入到Spring容器管理的类
(2). 写个配置类,要告诉Spring从哪些地方来找这些Bean
1. @Component 标注注解组件
2. @Configuration
@ComponentScan("day") 注明组件的位置,配置类相当于bean.xml配置文件
@Autowired 如果Spring容器检测到Weapon类的实例,就会自动注入进来
@Qualifier("axe")//-- 明确指定这个Bean
3. Spring容器获取Bean
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 武器Bean类 --> <bean id="weapon" class="day01.Axe"></bean> 骑士Bean类 <bean id="knight" class="day01.Knight"> 骑士Bean的武器属性 name="weapon" 的值一定要和Knight类的属性值一样 ref="weapon" 的值一定要和你配置的武器类Bean 的ID 一样 <property name="weapon" ref="weapon"></property> </bean> </beans>
import org.springframework.stereotype.Component; /** * 武器类(接口) * @author * */ public interface Weapon { void fire(); } //-- 斧头 class Axe implements Weapon{ @Override public void fire() { System.out.println("砍两下....."); } } class Gun implements Weapon{ @Override public void fire() { System.out.println("枪....."); } }
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** * 骑士类 * @author 儿子 * */ public class Knight { private Weapon weapon; public Knight() {} public Knight(Weapon weapon) { this.weapon = weapon; } public void setWeapon(Weapon weapon) { this.weapon = weapon; } public void attack() { weapon.fire(); } }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * 调用者 * */ public class Invoker { public static void main(String[] args) { /* 以下的代码是我们传统的构造Bean的方式 //-- 1. 武器 Weapon weapon = new Axe(); //-- 2. 骑士 Knight knight = new Knight(weapon); //-- 3. 骑士发起攻击 knight.attack(); //-- 4. 换武器: knight.setWeapon(new Gun()); knight.attack(); */ //-- 利用Spring框架来构建Bean对象 //-- 1. 构造Spring容器对象(利用xml文件的配置) ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); //-- 2. 通过Spring容器来获取想要的Bean Knight knight = (Knight)ctx.getBean("knight"); //-- 3. 骑士发起攻击 knight.attack(); } }
import org.springframework.stereotype.Component; /** * 武器类(接口) * @author * */ public interface Weapon { void fire(); } //-- 斧头 @Component("axe") class Axe implements Weapon{ @Override public void fire() { System.out.println("砍两下....."); } } @Component("gun") class Gun implements Weapon{ @Override public void fire() { System.out.println("枪....."); } }
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** * 骑士类 * @author 儿子 * */ @Component("knight") public class Knight { @Autowired //- 如果Spring容器检测到Weapon类的实例,就会自动注入进来 @Qualifier("axe")//-- 明确指定这个Bean private Weapon weapon; public Knight() {} public Knight(Weapon weapon) { this.weapon = weapon; } public void setWeapon(Weapon weapon) { this.weapon = weapon; } public void attack() { weapon.fire(); } }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; /** * Spring 容器的配置类,来代替那个Bean.xml文件 * 1. 类上面使用@Component来注解 * 2. 在配置类中使用@Bean 标注来注解你要实例化的类 * @author * */ @Configuration @ComponentScan("day01") //-- 告诉Spring从哪个包下寻找Component或者Bean public class BaseConfiguration { /*@Bean("a") public String A(){ //- 类似于@Component标注 return "a"; } @Bean("foo") public Foo foo() { return new Foo(); }*/ }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; /** * 调用者 * */ public class Invoker { public static void main(String[] args) { /* 以下的代码是我们传统的构造Bean的方式 //-- 1. 武器 Weapon weapon = new Axe(); //-- 2. 骑士 Knight knight = new Knight(weapon); //-- 3. 骑士发起攻击 knight.attack(); //-- 4. 换武器: knight.setWeapon(new Gun()); knight.attack(); */ //-- 1.构造Spring容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(BaseConfiguration.class); //-- 2. 获取Bean Knight knight = (Knight)ctx.getBean("knight"); // System.out.println(ctx.toString()); knight.attack(); // Axe axe = (Axe)ctx.getBean("axe"); // System.out.println(axe); // axe.fire(); } }
是一道经常出现在前端面试时的问题。如果只是简单的了解new关键字是实例化构造函数获取对象,是万万不能够的。更深入的层级发生了什么呢?同时面试官想从这道题里面考察什么呢?下面胡哥为各位小伙伴一一来解密。