Spring的三大主要特征
spring主要特征有三个:控制反转(IOC),依赖注入(DI)和面向切面(AOP)。
IoC:Inverse of Control(控制反转)
1.对控制反转的理解
- 传统方式:若要使用某个对象,需要自己去负责对象的创建,即new方式
- 控制反转:若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架
打个比喻:
- 传统方式:相当于你自己去市场new 了一只鸡,不过是生鸡,要自己拔毛,去内脏,再上香料,酱油,烤制,经过各种工序之后,才可以食用。
- 控制反转:相当于去肯德基(Spring)点了一只鸡,交到你手上的时候,已经五味俱全,你就只管吃就行了。
2.控制反转的主要形式有两种:依赖查找和依赖注入
- 依赖查找:容器提供回调接口和上下文条件给组件。EJB和Apache Avalon 都使用这种方式。这样一来,组件就必须使用容器提供的API来查找资源和协作对象,仅有的控制反转只体现在那些回调方法上(也就是上面所说的 类型1):容器将调用这些回调方法,从而让应用代码获得相关资源。
- 依赖注入:组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造函数参数传入的做法称为构造器注入(Constructor Injection)。
一.创建Spring项目
在IDEA中创建Spring项目,编译器会自动导入相关的jar包,如下图:
二.在 Packge【com】下新建一个【Source】类:
package com;
public class Source {
private String fruit;
private String sugar;
private String size;
private String ice;
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
public String getSugar() {
return sugar;
}
public void setSugar(String sugar) {
this.sugar = sugar;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getIce() {
return ice;
}
public void setIce(String ice) {
this.ice = ice;
}
}
三.在 【src】 目录下新建一个 【applicationContext.xml】 文件,通过 xml 文件配置的方式装配我们的 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 name="source" class="com.Source">
<property name="fruit" value="橙子"/>
<property name="sugar" value="正常糖"/>
<property name="size" value="大杯"/>
<property name="ice" value="多冰"/>
</bean>
</beans>
四.在 Packge【test】下新建一个【TestSpring】类:
package test;
import com.Source;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Source source = (Source) context.getBean("source");
System.out.println(source.getFruit());
System.out.println(source.getSugar());
System.out.println(source.getSize());
System.out.println(source.getIce());
}
}
代码结构图如下:
运行结果:
总结:
传统的方式:
通过new 关键字主动创建一个对象
IOC方式:
对象的生命周期由Spring来管理,直接从Spring那里去获取一个对象。 IOC是控制反转 (Inversion Of Control)的缩写,就像控制权从本来在自己手里,交给了Spring。
DI:Dependency Injection(依赖注入)
指 Spring 创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象
上面也解释了这个概念,其实现方式有三种:属性注入(setter注入),构造器注入和自动装配。
一.属性注入
1.重新创建一个Spring项目,在src目录下创建com和test包
2.在com包下创建Students类和Classes类
package com;
public class Students {
private String name;
private String sex;
private int age;
private Classes classes;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
}
package com;
public class Classes {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.在src目录下创建applicationContext.xml文件,通过 xml 文件配置的方式装配我们的 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 name="students" class="com.Students">
<property name="name" value="小关"/>
<property name="sex" value="男"/>
<property name="age" value="19"/>
<property name="classes" ref="classes"/>
</bean>
<bean name="classes" class="com.Classes">
<property name="id" value="6"/>
<property name="name" value="六班"/>
</bean>
</beans>
4.在test包下创建测试类
package test;
import com.Students;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring {
@org.junit.Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Students students = (Students) context.getBean("students");
System.out.println(students.getName());
System.out.println(students.getSex());
System.out.println(students.getAge());
System.out.println(students.getClasses().getId());
System.out.println(students.getClasses().getName());
}
}
运行结果如下图:
以上,就是属性注入。关键的是在类里面声明属性,写set方法,然后在xml里面配置bean和property的值。
二.构造器注入
构造器注入,就是在构造器里面注入依赖对象。其实跟属性注入差不多,先定义一个有参构造器,然后配置xml文件就行了。
1.在之前的基础上将Students类和Classes类进行修改
package com;
public class Students {
private String name;
private String sex;
private int age;
public Students(String name,String sex,int age){
this.name = name;
this.sex = sex;
this.age = age;
}
@Override
public String toString() {
return "{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}
package com;
public class Classes {
private Students students;
public Classes(Students students){
this.students = students;
}
@Override
public String toString() {
return "Classes{" +
"students=" + students +
'}';
}
}
2.修改applicationContext.xml文件
<?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 name="classes" class="com.Classes">
<constructor-arg ref="student"/>
</bean>
<bean name="student" class="com.Students">
<constructor-arg value="小关"/>
<constructor-arg value="男"/>
<constructor-arg value="19"/>
</bean>
</beans>
3.修改测试类
package test;
import com.Classes;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring {
@org.junit.Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Classes classes = context.getBean(Classes.class);
System.out.println(classes.toString());
}
}
运行结果如下:
三.自动装配
…博主也不是很懂,以后再补上。
AOP:Aspect Oriented Program(面向切面)
AOP 即 Aspect Oriented Program 面向切面编程
如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用。
在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能。
- 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务
- 所谓的周边功能,比如性能统计,日志,事务管理等等
周边功能在 Spring 的面向切面编程AOP思想里,即被定义为切面。
在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发,然后把切面功能和核心业务功能 “编织” 在一起,这就叫AOP。
AOP 的目的:
AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
AOP 当中的概念:
转载于:https://blog.csdn.net/qukaiwei/article/details/50367761
- 通知(Advice)
就是你想要的功能,也就是上面说的 安全,事物,日志等。你给先定义好把,然后在想用的地方用一下。 - 连接点(JoinPoint)
这个更好解释了,就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。 - 切入点(Pointcut)
上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。 - 切面(Aspect)
切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。 - 引入(introduction)
允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗 - 目标(target)
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。 - 代理(proxy)
怎么实现整套aop机制的,都是通过代理。 - 织入(weaving)
把切面应用到目标对象来创建新的代理对象的过程。
关键就是:切点定义了哪些连接点会得到通知