1.什么是spring
- spring是一个开源框架,spring为简化企业级开发而生,使用spring可以使简单的java bean 实现以前只有EJG才能实现的功能
- spring是一个IOC和AOP容器框架
2.spring的特点
- 轻量级 spring是非侵入性的 - 基于spring应用的开发中的对象可以不依赖于spring的API
- 依赖注入 DI
- 面向切面编程 AOP
- 容器 spring是一个容器,因为它包含和管理应用对象的生命周期
- 框架 spring实现了使用简单的组件配置组合成一个复杂的应用,在spring中可以使用xml和java注解组合这些对象
- 一站式 在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库
3 Spring容器
在Spring IOC 容器读取bean配置、创建bean之前,必须对他进行实例化,只有在容器实例化后,才能从IOC容器里获取bean实例并使用它
3.1 spring提供了两种类型的IOC容器实现
- BeanFactory: IOC容器的基本实现
- ApplicationContext: 提供了更多的高级特性,是BeanFactory的子接口
BeanFactory是Spring框架的基础设施,面向Spring本身;ApplicationContext面向Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory
4 IOC
4.1 什么是IOC
IOC(Inversion of Controller)其思想是反转资源获取的方向,传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,适时得返回资源。Dog dog = new Dod();而使用了IOC之后,则是容器主动得将资源推送给他所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源,这种行为也被称为查找的被动方式。
4.2 什么是DI
DI(Dependency Injection)IOC的另一种表述方式:即组件以一些预定义好的方式(例如:setter方法),接受来自容器的资源注入,相对于IOC而言,这种表述更直接
5 Bean的配置方式
5.1 通过全类名(反射)
<bean id="person1" class="com.example.demo.bean.Person"> <property name="name" value="dong"/> <property name="age" value="12"/> </bean>
- 1
- 2
- 3
- 4
5.2 通过工厂方法(静态工厂方法&实例工厂方法)
调运静态工厂方法创建Bean是将对象创建的过程封装到静态方法中,当客户端需要对象时,只需要简单地调用静态方法,而不用关心创建对象的细节。
要声明通过静态方法创建的Bean,需要在Bean的class属性里指定拥有该工厂的方法的类,同时在factory-method属性里指定工厂方法的名称。最后,使用constrctor-arg元素为该方法传递方法参数。
<bean id="simpleDateFormat" class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd hh:mm:ss"/> </bean> <bean id="date" factory-bean="simpleDateFormat" factory-method="parse"> <constructor-arg value="2018-11-11 11:11:11"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
5.3 FactoryBean
Spring中有两种类型的Bean,一种是普通Bean,一种是工厂Bean,即FactoryBean。
工厂Bean和普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象
public class PersonFactoryBean implements FactoryBean<Person>{ // 返回对象 @Override public Person getObject() throws Exception { Person person = new Person(); person.setId(2); person.setName("zhu"); person.setAge(20); return person; } //返回类型 @Override public Class<?> getObjectType() { return Person.class; } //是否是单例 @Override public boolean isSingleton() { return true; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
5.4 基于注解配置
Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的Bean组件
<context:component-scan base-package="com.girhub.dge1992.bean"/>
- 1
特定组件包括:
- @Component:基本注解,表示了一个受Spring管理的Bean组件
- @Respository:标识持久层Bean组件
- @Service:标识服务层Bean组件
- @Controller:标识表现层Bean组件
自动装配类型:
- @Autowired:根据类型自动装配
- @Resource:注解要求提供一个Bean名称的属性,若该属性为空,则自动采用标注处的变量和方法名作为Bean的名称
- @Inject:和@Autowired很像,只是没有reqired属性
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写,也可以在注解中通过value属性值标识组件的名称
6 依赖注入的方式
spring支持3种依赖注入的方式
6.1 属性注入
使用对象的set方法
<bean id="person1" class="com.github.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> </bean>
- 1
- 2
- 3
- 4
6.2 构造器注入
使用对象的构造函数
<bean id="person2" class="com.github.dge1992.bean.Person"> <constructor-arg value="dong" index="0" type="java.lang.String"></constructor-arg> <constructor-arg value="23" index="1" type="java.lang.Integer"></constructor-arg> </bean>
- 1
- 2
- 3
- 4
6.3 工厂方法注入(很少使用不推荐)
7 注入属性值细节
7.1 字面值
可以用字符串表示的值,可以通过元素标签或value属性进行注入。
基本数据类型及其封装类、String等类型都可以采用字面值注入的方式。
若字面值中包含特殊字符,可以通过<![CDATA[]]>把字面值包裹起来。 <bean id="car1" class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔驰>]]></value> </property> <property name="type" value="高档车"/> <property name="price" value="1000"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
7.2 引用其他bean
组成应用程序的bean经常需要相互协助以完成应用程序的功能,要使bean能够互相访问,就必须在bean配置文件中指定对bean的引用。
在bean的配置文件中,可以通过元素或ref属性为bean的属性或构造器参数指定对bean的引用。
也可以在属性或构造器里包含bean的声明,这样的bean成为内部bean.
<bean id="car1" class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔驰>]]></value> </property> <property name="type" value="高档车"/> <property name="price" value="1000"/> </bean> <bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="car" ref="car1"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
7.3 注入参数详解:null和级联属性
可以使用专用的元素标签为bean的字符串或其他对象类型的属性注入null值,spring支持级联属性的配置。
<bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="car" ref="car1"/> <property name="car.name" value="奔驰"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
7.4 集合属性
在spring中可以通过一组内置的xml标签(例如:,,)来配置集合属性。通过指定简单的常量值,通过指定对其他bean的引用,通过指定内置bean定义,通过指定空元素。
java.util.Map通过标签定义,标签里可以使用多个作为子标签,普通常量使用key和value来定义,bean引用通过key-ref和value-ref属性定义。.
使用utility scheme 定义集合
使用p命名空间,简化xml文件的配置
<bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="cars"> <list> <bean class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔驰>]]></value> </property> <property name="type" value="高档车"/> <property name="price" value="1000"/> </bean> <bean class="com.girhub.dge1992.bean.Car"> <property name="name"> <value type="java.lang.String"><![CDATA[<奔驰111>]]></value> </property> <property name="type" value="高档车111"/> <property name="price" value="1000111"/> </bean> </list> </property> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
集合引用外部bean
<bean id="person1" class="com.girhub.dge1992.bean.Person"> <property name="name" value="feng"/> <property name="age" value="3"/> <property name="cars"> <list> <ref bean="car1"/> <ref bean="car2"/> </list> </property> <property name="names"> <list> <value>AAA</value> <value>BBB</value> </list> </property> <property name="carMap"> <map> <entry key="first" value-ref="car1"/> <entry key="second" value-ref="car2"/> </map> </property> <property name="nameMap"> <map> <entry key="firstName" value="CCC"/> <entry key="secondName" value="DDD"/> </map> </property> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
8 自动装配
8.1 bean的自动装配(注解注入时用到)
Spring IOC 容器可以自动配置bean,需要做的仅仅是在的autowite属性里指定自动装配的模式
- byType(根据类型自动装配)
- byName(根据名称自动装配)
8.2 bean自动装配的缺点
在Bean配置文件里设置autowire属性进行自动装配将会装配bean的所有属性。然而,若只希望装配个别属性时,autowire属性就不灵活了。
autowire属性要么根据类型自动装配,要么根据名称自动装配,不能两者一起使用。
9 bean之间的关系
9.1 继承
Spring允许继承bean的配置,被继承的bean成为父bean,继承这个bean的bean成为子bean,子bean从父bean中继承配置,也可以覆盖bean继承过来的配置。
<bean id="person1" class="com.girhub.dge1992.bean.Person" p:name="dong" p:car-ref="car1"/> <bean id="person2" class="com.girhub.dge1992.bean.Person" parent="person1"/>
- 1
- 2
9.2 依赖
Spring允许用户通过 depends-on 属性设置 bean 前置依赖的bean,前置依赖的bean会在本bean实例化之前创建好。
<bean id="car1" class="com.girhub.dge1992.bean.Car"> <property name="name" value="宝马"/> </bean> <bean id="person3" class="com.girhub.dge1992.bean.Person" depends-on="car1"/>
- 1
- 2
- 3
- 4
10 bean的作用域
在Spring中,可以在元素的scope属性里设置bean的作用域。
默认情况下,Spring只为每个在IOC容器里声明的Bean创建唯一一个实例,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和Bean引用都将返回这个唯一的Bean实例,该作用域被称为singleton,他是所有bean的默认作用域。
类别 说明 singleton 在Spring容器中仅存在一个bean实例,bean以单例是形式存在 prototype 每次调用getBean(),都会返回一个新的实例 request 每次HTTP请求都会创建一个新的实例,该作用域适用于WebApplicationContxt环境 session 同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean。该作用域只适合WebApplicationContxt环境
11 使用外部属性文件
11.1 使用外部属性文件的好处
完成属性值和bean的配置的分离,实现解耦
11.2 IOC容器如何引用外部文件
<context:property-placeholder location="文件路径">
- 1
11.3 如何引用外部属性文件的值
属性文件一般是 *.properties 数据以key=value的形式 通过${key}获取
12 Spring表达式语言:SpringEL
12.1 简介
Spring表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言
12.2 使用方法
使用#{…}作为定界符
12.3 SpEL的实现
- 通过bean的id对bean进行引用
- 调用方法以及引用对象中的属性
- 计算表达式的值
- 正则表达式的匹配
<bean id="car1" class="Car"> <property name="name" value="宝马"/> <property name="price" value="10"/> </bean> <bean id="person1" class="Person"> <property name="name" value="dong"/> <property name="car" value="#{car1}"/> <property name="age" value="10"/> </bean> <bean id="person2" class="Person"> <property name="name" value="#{person1.name.toUpperCase()}"/> <property name="car" value="#{car1}"/> <property name="age" value="#{person1.age + 10}"/> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
13. bean的生命周期
Spring IOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务。在Bean的声明里设置init-method 和 destroy-method属性,为Bean设置初始化和销毁方法。
Spring IOC容器对Bean的生命周期进行生命周期管理的过程:
- 通过构造器或工厂方法创建Bean实例
- 为Bean的属性设置值和对其他Bean的引用
- (后置处理器前置方法执行)(可选)
- 调用Bean的初始化方法
- (后置处理器后置方法执行)(可选)
- 可以使用Bean了
- 当容器关闭时,调用Bean的销毁方法
13.1 Bean后置处理器
Bean后置处理器允许在调用初始化方法前后对Bena进行额外的处理。
Bean后置处理器对IOC容器里的所有Bean实例逐一处理,而非单一实例,其典型作用是:检查Bean属性的正确性或根据特定的标准更改Bena的属性。
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("后置处理器前置方法执行"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("后置处理器后置方法执行"); return bean; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
14. AOP
名称 | 简介 |
---|---|
连接点 | 程序运行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点,相对点表示的位置。 |
切点 | AOP通过切点定位到特殊的连接点。类比:连接点相当于数据库中的记录,切点相当于查询条件。 |
切面 | 横切关注点被模块化的特殊对象。 |
通知 | 切面必须要完成的工作 |
目标 | 被通知的对象 |
代理 | 向目标对象应用通知之后创建的对象 |
14.1 Java中的代理
代理是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
14.2 Java动态代理
public class CalculateProxy { //代理对象 private Calculate calculate; public CalculateProxy(Calculate calculate) { this.calculate = calculate; } public Calculate getCalculateProxy(){ ClassLoader classLoader = Calculate.class.getClassLoader(); Class[] interfaces = {Calculate.class}; InvocationHandler handler = new InvocationHandler() { /** * * @param proxy 代理的对象 * @param method 被代理对象的方法 * @param args 方法参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Arrays.stream(args).forEach(e -> System.out.println("参数是:" + e)); //calculate是目标对象 Object invoke = method.invoke(calculate, args); System.out.println("结果是:" + invoke); return invoke; } }; /** * ClassLoader: 指定当前目标对象使用类加载器,获取加载器的方法是固定的 * Class<?>[]: 目标对象实现的接口的类型,使用泛型方式确认类型 * InvocationHandler h: 事件处理,执行目标对象的方法时,会触发事件处理器的方法, * 会把当前执行目标对象的方法作为参数传入 */ Calculate calculate = (Calculate) Proxy.newProxyInstance(classLoader, interfaces, handler); return calculate; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
14.3 Cglib动态代理
public class ProxyFactory implements MethodInterceptor { private Object target; public ProxyFactory(Object target) { this.target = target; } public Object getProxyInstance(){ //1.工具类 Enhancer en = new Enhancer(); //2.设置父类 en.setSuperclass(target.getClass()); //3.设置回调函数 en.setCallback(this); //4.创建子类(代理对象) return en.create(); } @Override public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("111"); Object invoke = method.invoke(target, args); System.out.println("222"); return invoke; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
14.4 AOP简介
AOP(面向切面编程):是一种新的方法论,是对传统OOP(面向对象编程)的补充
AOP的主要编程对象是切面,而切面模块化横切关注点
在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能在哪里。这样一来横切关注点就被模块化到特殊的对象里。14.5 AOP的好处
- 每个事物逻辑位于一个位置,代码不分散,便于维护和升级
- 业务模块更简洁,只包含核心业务代码
转自:http://blog.csdn.net/dongganen/article/details/79007736