Spring 快速入门
快速入门
Spring是一个管理Bean的容器,一个轻量级框架
-
使用Spring,需要引入对应的依赖下载地址
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <springFramework.version>5.1.5.RELEASE</springFramework.version> </properties> <dependencies> <!-- spring相关 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${springFramework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${springFramework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springFramework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${springFramework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${springFramework.version}</version> </dependency> <!--日志--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> </dependencies>
-
管理对象,必须是一个接口一个实现类
/** * 战士 */ public interface Fighter { void show(); }
/** * 吕布,战士类的一个实现类 */ public class LvBu implements Fighter { public void show() { System.out.println("战士吕布"); } }
IOC控制反转/DI依赖注入
回顾历史
之前我们创建对象的方式,是在一个类中主动new另一个类的对象,然后再调用其方法完成功能
public class Main {
public static void main(String[] args) {
// 获取对象 -- 以前的方式,主动创建
Fighter f1 = new LvBu();
f1.show();
}
}
Main类掌握着Fighter类型对象的控制权(想创建就创建),这样带来一个缺点,当许多模块都需要使用Fighter类型对象时,一旦Fighter类型对象需要发生改变,需要大量的修改其他模块的代码才能满足需求,所以,Spring提出了一种新的获取对象的方式 -- 配置
spring配置文件
spring.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-3.0.xsd">
<!--配置一个对象-->
<!--LvBu lvbu = new LvBu();-->
<bean id="lvbu" class="com.neuedu.test.LvBu"></bean>
<bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
</beans>
public class Main {
public static void main(String[] args) {
// 获取对象 -- 以前的方式,主动创建
// Fighter f1 = new LvBu();
// f1.show();
// Spring的方式获取对象,需要把对象配置在xml文件中
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
Fighter lvbu = (Fighter)applicationContext.getBean("lvbu");
Fighter guanyu = (Fighter)applicationContext.getBean("guanyu");
lvbu.show(); // 战士吕布
guanyu.show(); // 战士关羽
}
}
使用配置的方式带来一个好处,当Fighter类型对象需要改变的时候,我们只需要修改spring.xml
就可以了,不需要修改其他模块,便利了开发
IOC控制反转
对于java应用程序来说,对象的控制权逆转了,这个概念称为IOC--控制反转
DI依赖注入
对于spring来说,配置一个对象,相当于对其他调用者注入了一个可调用的对象
IOC控制反转和DI依赖注入没有区别,只是针对参照物不同的不同说法
属性注入
-
构造器注入(前提:必须有有参构造器)
<!--默认是调用无参构造器创建对象的,若没有无参构造器,会报错--> <bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
public class GuanYu implements Fighter { private String name; private int age; public GuanYu() {} public GuanYu(String name, int age) { this.name = name; this.age = age; } public void show() { System.out.println(name+","+age); } }
<!--利用有参构造器进行属性注入--> <bean id="guanyu" class="com.neuedu.test.GuanYu"> <!--构造器注入属性--> <!--给对象的name属性,赋值“关羽”--> <constructor-arg name="name" value="关羽"></constructor-arg> <!--给对象的age属性,赋值14--> <constructor-arg name="age" value="14"></constructor-arg> </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-3.0.xsd"> <bean id="guanyu" class="com.neuedu.test.GuanYu"> <constructor-arg name="name" value="关羽"></constructor-arg> <!--属性注入如果是对象,需要用ref关联另一个对象id--> <constructor-arg name="weapon" ref="qinglong"></constructor-arg> </bean> <!--配一个QingLong--> <bean id="qinglong" class="com.neuedu.test.QingLong"> <property name="dps" value="50"></property> </bean> </beans>
集合
-
setter注入
<bean id="guanyu" class="com.neuedu.test.GuanYu"> <!--利用set方法注入属性--> <property name="name" value="关羽坤"></property> <property name="age" value="144"></property> </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-3.0.xsd"> <bean id="guanyu" class="com.neuedu.test.GuanYu"> <property name="name" value="关羽"></property> <!--属性注入如果是对象,需要用ref关联另一个对象id--> <property name="weapon" ref="qinglong"></property> </bean> <!--配一个QingLong--> <bean id="qinglong" class="com.neuedu.test.QingLong"> <property name="dps" value="50"></property> </bean> </beans>
集合
<bean id="guanyu" class="com.neuedu.test.GuanYu"> <property name="name" value="关羽"></property> <!--属性注入如果是对象,需要用ref关联另一个对象id--> <property name="weapon" ref="qinglong"></property> <!--List<String>--> <property name="boy"> <list> <value>张飞</value> <value>马超</value> </list> </property> <!--List<Weapon>--> <property name="repository"> <list> <ref bean="qinglong"></ref> <ref bean="fang"></ref> </list> </property> <!--Map<String,String>--> <property name="horse"> <map> <entry key="坐骑1" value="赤兔"></entry> <entry key="坐骑2" value="的卢"></entry> </map> </property> <!--Map<String,Weapon>--> <property name="weaponMap"> <map> <entry key="武器1" value-ref="qinglong"></entry> <entry key="武器2" value-ref="fang"></entry> </map> </property> </bean>
- 接口注入(Spring不支持)
自动装配(了解)
<!-- ==========================自动按名字装配autowire=byName=========================== -->
<!-- ==========================自动按类型装配autowire=byType=========================== -->
<bean id="qiyi" class="com.neuedu.test1.QiYi" autowire="byType"/>
<!-- 当按照类型装配时,有多个符合条件的对象,需要指定primary="true"表明是主要的装配对象 -->
<bean id="wuqi" class="com.neuedu.test1.FaZhang" primary="true">
<property name="name" value="大法师之杖"></property>
</bean>
<bean id="kandao" class="com.neuedu.test1.KanDao">
<property name="name" value="大法师砍刀"></property>
</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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 开启注解 -->
<context:annotation-config />
<bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
<bean id="abc1" class="com.neuedu.test.QingLong">
<qualifier value="test1"></qualifier>
</bean>
<bean id="abc2" class="com.neuedu.test.Fang">
<qualifier value="test2"></qualifier>
</bean>
</beans>
package com.neuedu.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class GuanYu implements Fighter {
private String name = "关羽";
@Autowired
@Qualifier("test2")// 转配的com.neuedu.test.Fang
private Weapon weapon;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public void show() {
System.out.println(name);
weapon.showInfo();
}
}
注解自动装配(重要)
spring.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.neuedu.test"></context:component-scan>
<bean id="guanyu" class="com.neuedu.test.GuanYu"></bean>
</beans>
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
GuanYu guanyu = (GuanYu)applicationContext.getBean("guanyu");
guanyu.show();
}
}
@Component("test1")
public class QingLong implements Weapon {
private int dps;
public void setDps(int dps) {
this.dps = dps;
}
public int getDps() {
return dps;
}
public void showInfo() {
System.out.println("青龙偃月,攻击力很高");
}
}
@Component("test2")
public class Fang implements Weapon {
private int dps;
public void setDps(int dps) {
this.dps = dps;
}
public int getDps() {
return dps;
}
public void showInfo() {
System.out.println("方天画戟,攻击力很高");
}
}
@Component
public class GuanYu implements Fighter {
private String name = "关羽";
@Autowired
@Qualifier("test2")
private Weapon weapon;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public void show() {
System.out.println(name);
weapon.showInfo();
}
}
类型 说明
@Component 通用的构造型注解,标示该类为Spring 组件。
@Controller 标识将该类定义为Spring MVC controller。
@Repository 标识将该类定义为数据仓库(例如:Dao层)。
@Service 标识将该类定义为服务(例如:Service层)。
AOP面向切面编程
-
一般应用在如性能检测、访问控制、事务控制、日志记录等
-
切面(Aspect)
切面是切点和通知组成,通知和切点共同定义了切面的全部内容即:它是什么,在何时何处完成其功能;
- 连接点(Joinpoint)
连接点是在应用执行过程中能够插入切面的一个点,Spring仅支持方法的连接点,即仅能在方法调用前,方法调用后,方法抛出异常时及方法调用前后插入切面代码。
- 切点(Pointcut)
切点定义了在何处应用切面,AOP通过“切点”定位特定的连接点。切点相当于查询条件,一个切点可以匹配多个连接点。
- 通知(Advice)
切面的工作被成为通知,定义了切面是什么及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题,它应该在某个方法被调用之前?之后?等。
- Spring切面可以应用5种类型的通知:
- 前置通知(Before)在目标方法被调用之前调用通知功能;
- 后置通知(After)在目标方法被完成之后调用通知功能,不关心方法的输出是什么;
- 环绕通知(Around advice)通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为;
- 异常通知(After-throwing)在目标方法抛出异常后调用通知;
- 返回通知(After-returning)在目标方法成功执行之后调用通知;