Spring知识点
1.Spring是什么,有什么优点?
- Spring是一个开源的免费框架
- Spring是一个轻量级的、非入侵室的框架
- 控制反转(IOC),面向切面编程(AOP)
- 支持事物的出来,对框架整合的支持
2.Spring Boot 和Spring Cloud
Spring Boot是一个快速开发的脚手架,基于SpringBoot可以快速的开发单个微服务
Spring Cloud是一系列框架的有序集合。
3.IOC(Inversion of Control)控制反转
- 控制反转是一种设计思想
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。
4.IOC创建对象的方式
4.1 使用无参构造对象,默认
<bean id="hello" class="com.lin.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
4.2使用有参构造(构造器注入)
- 下标赋值
<bean id="hello_01" class="com.lin.pojo.Hello">
<constructor-arg index="0" value="Summer"/>
</bean>
- 类型赋值(不推荐使用)
<bean id="hello_02" class="com.lin.pojo.Hello">
<constructor-arg type="java.lang.String" value="Winter"/>
</bean>
- 参数名
<bean id="hello_03" class="com.lin.pojo.Hello">
<constructor-arg name="str" value="Autumn"/>
</bean>
bean = 对象
id = 唯一标识
class = new的对象
property = 相当于给对象中的属性设值
constructor-arg = 有参构造器
4.3 pojo
package com.lin.pojo;
public class Hello {
private String str;
public Hello(){}
public Hello(String str) { this.str = str; }
public String toString() {
return "Hello " + str+" ! ! !" ;
}
public String getStr() { return str; }
public void setStr(String str) { this.str = str; }
}
4.4 test
import com.lin.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取Spring上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//对象都在Spring中管理直接取出就可以用
Hello hello = (Hello) context.getBean("hello");
Hello hello1 = (Hello) context.getBean("hello_01");
Hello hello2 = (Hello) context.getBean("hello_02");
Hello hello3 = (Hello) context.getBean("hello_03");
System.out.println(hello.toString());
System.out.println(hello1.toString());
System.out.println(hello2.toString());
System.out.println(hello3.toString());
}
}
4.5输出结果
5.DI依赖注入
5.1构造器注入
5.2.set方式注入(重点,案例讲解)
5.2.1 pojo(包)
package com.lin.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> gnames;
private String wife;
private Properties info;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
public String[] getBooks() { return books; }
public void setBooks(String[] books) { this.books = books; }
public List<String> getHobbys() { return hobbys; }
public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; }
public Map<String, String> getCard() { return card; }
public void setCard(Map<String, String> card) { this.card = card; }
public Set<String> getGnames() { return gnames; }
public void setGnames(Set<String> gnames) { this.gnames = gnames; }
public String getWife() { return wife; }
public void setWife(String wife) { this.wife = wife; }
public Properties getInfo() { return info; }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", gnames=" + gnames +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
public void setInfo(Properties info) { this.info = info; }
}
package com.lin.pojo;
public class Address {
private String address;
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
@Override
public String toString() {
return "Address{" + "address='" + address + '\'' + '}';
}
}
5.2.2 beans.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.lin.pojo.Address">
<property name="address" value="东京"/>
</bean>
<bean id="student" class="com.lin.pojo.Student">
<!--第一种,普通的注入,value-->
<property name="name" value="新的开始"/>
<!--第二种,Bean注入-->
<property name="address" ref="address"/>
<!--数组-->
<property name="books">
<array>
<value>java入门</value>
<value>java精通</value>
<value>java底层</value>
</array>
</property>
<!--list-->
<property name="hobbys">
<list>
<value>唱</value>
<value>跳</value>
<value>Rap</value>
</list>
</property>
<!--Map 属性注入比较特殊-->
<property name="card">
<map>
<entry key="银行卡" value="1111-2222-3333"/>
<entry key="社保卡" value="4444-5555-6666"/>
</map>
</property>
<!--Set-->
<property name="gnames">
<set>
<value>LOL</value>
<value>CF</value>
<value>CSK</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties 属性注入比较特殊-->
<property name="info">
<props>
<prop key="driver">com.mysql.jdbc.drive</prop>
<prop key="url">jdbc:mysql://localhost</prop>
<prop key="user">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
</beans>
5.2.3 test(测试类)
import com.lin.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
}
5.2.4 运行结果
5.3拓展方式注入(案例讲解)
- p标签和c标签注入
5.3.1 pojo
package com.lin.pojo;
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
5.3.2 user.xml
P命名约束: xmlns:p="http://www.springframework.org/schema/p
C命名约束:xmlns:c=“http://www.springframework.org/schema/c”
5.3.3 test
@Test
public void testPC(){
ApplicationContext context = new ClassPathXmlApplicationContext("user.xml");
System.out.println(context.getBean("userP"));
System.out.println(context.getBean("userC"));
}
5.3.4运行结果
6.Bean的四大作用域
- singleton:单例模式, spring中的单例是基于BeanFactory的,在容器中只有一个
<bean id="student" class="com.lin.pojo.Student" scope="singleton">
- prototype:原型模式, 从此容器中获取bean,会返回一个新的实例, 一个bean对应多个实例,创建容器的时候并没有实例化,当获取的时候才去创建,并且每次获取的都不一样。 (无状态的bean使用单例,有状态的使用原型)
<bean id="student" class="com.lin.pojo.Student" scope="prototype">
- request :每次http请求都会创建新的bean,仅适用于WebApplicationContext。一个bean对应一个实例,但是每个请求都有各自的bean实例
<bean id="student" class="com.lin.pojo.Student" scope="request">
- session:相同http session共享一个bean,容器会返回该Bean的同一实例;不同的Session请求则会创建新的实例,该bean实例仅在当前Session内有效;不同的实例之间不共享属性,且实例仅在自己的session请求内有效,请求结束,则实例将被销毁。仅适用于WebApplicationContext
<bean id="student" class="com.lin.pojo.Student" scope="session">
7.Bean的自动装配
7.1 Spring装配
- 自动装配是Spring满足bean一来的一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三种装配的方式
- 在xml中显示的配置
- 在java中显示的配置
- 隐式的自动装配bean【重点】
7.2 隐式的自动装配Bean
7.2.1环境搭建:一个人有两个宠物
package com.lin.pojo;
public class Cat {
public void shout(){
System.out.println("喵喵");
}
}
package com.lin.pojo;
public class Dog {
public void shout(){
System.out.println("汪汪");
}
}
package com.lin.pojo;
public class People {
private Cat cat;
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
7.2.2 ByName自动装配
<bean name="dog" class="com.lin.pojo.Dog"/>
<bean name="cat" class="com.lin.pojo.Cat"/>
<bean name="people" class="com.lin.pojo.People" autowire="byName">
<!--Byname自动装配:byname会自动查找在上下文查找,和自己对象set方法后面的值对应bean的id,可以省略显示的装配
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
-->
<property name="name" value="北鱼"/>
</bean>
7.2.3 ByType自动装配
<bean class="com.lin.pojo.Dog"/>
<bean class="com.lin.pojo.Cat"/>
<bean name="people" class="com.lin.pojo.People" autowire="byType">
<!--ByType自动装配:byType会自动查找在上下文查找,和自己对象属性相同的bean
可以省略显示的装配
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
-->
<property name="name" value="北鱼"/>
</bean>
7.2.4 byName和byType小结
- byName:需要保证所有的bean的id唯一,并且这个bean需要自动注入的属性和set方法的值一致
- byType:需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性类型一致
7.3使用注解自动装配
jdk1.5开始支持注解,spring2.5开始全面支持注解。
利用注解的方式注入属性,也可以在set方法上使用。
1.导入context约束
2.@Autowired使用在属性上使用,可以不用编写对于的set方法
package com.lin.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class People {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
如果@Autowired自动装配环境比较复杂。
<bean id="dog1" class="com.lin.pojo.Dog"/>
<bean id="dog2" class="com.lin.pojo.Dog"/>
<bean id="dog3" class="com.lin.pojo.Dog"/>
<bean id="cat1" class="com.lin.pojo.Cat"/>
<bean name="people" class="com.lin.pojo.People">
自动装配无法通过一个注解完成的时候,我们可以使用@Qualifier(value = “dog”)去配合使用,指定一个唯一的id对象,根据byName的方式自动装配,其中@Qualifier不能单独使用。
@Autowired
private Cat cat;
@Autowired
@Qualifier(value = "dog1")
private Dog dog;
如果没有指定唯一的id对象,就会报错,不能找到唯一一个对象
3.@Resource和@Autowired的异同
@Resoutce的使用与Autowired的使用类似
@Resource
private Cat cat;
@Resource(name = "dog1")
private Dog dog;
private String name;
@Autowired与@Resource异同:
同:
- @Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
异:
-
@Autowired为Spring提供的注解,装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false,默认按照byType注入,当同一个class拥有多个bean id,按照byName注入。
导入包:org.springframework.beans.factory.annotation.Autowired; -
@Resource默认按照ByName自动注入,由J2EE提供
@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。默认情况下,将通过反射机制使用byName自动注入策略。
导入包:javax.annotation.Resource
8.使用注解开发
在spring4之后,想要使用注解,必须要保证aop的包导入
使用注解需要导入contex的约束
使用注解注入属性
IOC注解详解:
@Component
修改一个类,将这个类交给Spring管理,相当于在配置文件当中配置
@Component的衍生注解(野生注解),会按照web开发中,mvc架构中分层
- dao层:(@Repository)——数据访问层(持久化层),CRUD操作
- service层:(@Service)——业务逻辑层,做一些业务逻辑地处理,并给控制层返回结果
- controller层:(@Controller)——控制层,接收用户传递过来的数据,调用业务逻辑层,根据业务逻辑层返回的结果
这四个注解功能一样的,都是代表将某个类注册到容器中
@scope
作用范围:
- singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
- prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收。
小结:
XML与注解:
- xml更加万能,适用于任何场合,维护简单方便
- 注解不是自己类使用不了,维护比较复杂
xml与注解的最佳实践:
- xml用来管理bean
- 注解只负责完成属性的注入
- 在使用注解时,要让注解生效,必须开启注解的支持
<!--指定注解扫描包-->
<context:component-scan base-package="com.lin.pojo"/>
<context:annotation-config/>
9.java方式配置Spring
JavaConfig是Spring4之后的推荐的配置方式,可以完全替代xml配置
Spring的java配置的方式是由@Configuration和@Bean注释实现
- @Configuration作用于类上,代表这是一个配置类,相当于一个xml配置文件
- @Bean作用在方法上,相当于xml配置文件中的bean标签,方法名=bean标签中的id属性,方法返回值=bean标签中的class属性
创建一个User对象
package com.lin.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
//这个类被Spring接管了,注册到容器中(可写,可不写)
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("lin") //属性注入值
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
创建一个config类
package com.lin.config;
import com.lin.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
//Spring容器托管,注册到容器中,因为他本来就是一个@Component
//@Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
@ComponentScan("com.lin.pojo")
public class LinConfig {
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User user(){
return new User(); //就是返回要注入到bean的对象
}
}
编写一个测试类
import com.lin.config.LinConfig;
import com.lin.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置类的方式,我们就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象来加载
ApplicationContext context = new AnnotationConfigApplicationContext(LinConfig.class);
User getUser = (User) context.getBean("user");
System.out.println(getUser.getName());
}
}
注:这种纯java配置,在SpringBoot随处可见