关于Spring的学习开始了。期待一下。
目录
springMVC的MAVEN项目简单搭建
新建项目:
以上,都可以二选一,这章节讲的很简单,所以java或者web项目都可以。
结构目录如下:
配置Maven
window -- preferences -- Maven -- User Settings设置maven
我的maven是用了阿里的镜像
D:\develop\xiaogaoxiang
nexus-aliyun
*
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
我已经把里面之前注释的内容去掉了,按照需要添加。
上面一个maven项目已经搭建起来。
关于xml配置文件的简单介绍
1、既然将spring相关内容,则先给项目增加spring的核心jar包。修改pom.xml文件:
4.0.0
com.bmyn
bmyn
0.0.1-SNAPSHOT
jar
bmyn
http://maven.apache.org
UTF-8
org.springframework
spring-context
5.0.6.RELEASE
jUnit
jUnit
4.12
test
加完之后,因为采用了阿里的镜像,因此下载的十分快,几乎没有感觉。
2、新建立一个Person实体类
package com.blmyn.java.springtest.cap1;
/**
*
* @FileName Person.java
* @Author xiaogaoxiang
* @At 2018年11月29日 下午10:15:31
* @Desc 用户类
*/
public class Person {
private String name;
private Integer age;
public Person() {
super();
}
public Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
建立一个beans.xml配置文件,将该Person类注入到容器中
写一个测试类:
package com.blmyn.java.springtest.cap1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest1 {
public static void main(String[] args) {
@SuppressWarnings("resource")
// 将beans.xml加入到容器中
ApplicationContext atx = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person) atx.getBean("person");
System.out.println(person);
}
}
控制台输出结果:
十一月 29, 2018 11:32:28 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@45ff54e6: startup date [Thu Nov 29 23:32:28 CST 2018]; root of context hierarchy
十一月 29, 2018 11:32:28 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
Person [name=xiaogaoxiang, age=27]
我们看到最下面输出了Person类中的toString()方法。
测试不用配置文件(.xml),而是使用注解的方式把Person进行注入
package com.blmyn.java.springtest.cap1.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.blmyn.java.springtest.cap1.Person;
/**
*
* @FileName MainConfig.java
* @Author xiaogaoxiang
* @At 2018年11月29日 下午10:27:42
* @Desc 配置文件
*/
@Configuration // 增加该注解,表示该Java文件等同于xml配置文件
public class MainConfig {
@Bean
public Person person() {
return new Person("xiaogaoxiang", 28);
}
}
我们可以看到,给一个类上面增加了一个:@Configuration注解,表示该类就等同于beans.xml文件
进行测试:
package com.blmyn.java.springtest.cap1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.blmyn.java.springtest.cap1.config.MainConfig;
public class MainTest2 {
public static void main(String[] args) {
@SuppressWarnings("resource")
// 把配置文件注入到容器中
ApplicationContext act = new AnnotationConfigApplicationContext(MainConfig.class);
Person person = (Person) act.getBean("person");
System.out.println(person);
String[] beanDefinitionNames = act.getBeanDefinitionNames();
for (String bdn : beanDefinitionNames) {
System.out.println(bdn);
}
}
}
控制台输出结果:
十一月 29, 2018 11:36:13 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5b37e0d2: startup date [Thu Nov 29 23:36:13 CST 2018]; root of context hierarchy
Person [name=xiaogaoxiang, age=28]
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
我们可以看到,注入之后,将Person进行实例化,并将所有的注入的名称全部打印。
关于ComponentScan扫描规则
先来看看配置类
package com.blmyn.java.springtest.cap2.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import com.blmyn.java.springtest.cap1.Person;
/**
*
* @FileName Cap2MainConfig.java
* @Author xiaogaoxiang
* @At 2018年11月29日 下午10:34:49
* @Desc 配置文件
*/
// @Configuration === 配置文件
@Configuration
// @ComponentScan制定扫描规则
@ComponentScan(value = "com.blmyn.java.springtest.cap2", includeFilters = {
@Filter(type = FilterType.CUSTOM, classes = { CansluckTypeFilter.class }) }, useDefaultFilters = false)
public class Cap2MainConfig {
@Bean
public Person person() {
return new Person("xiaogaoxiang", 28);
}
}
增加了@ComponentScan注解,此注解的value为指定要扫描的包
1、首先我们指定value,表示要扫描com.blmyn.java.springtest.cap2下面的所有包。如果不加后面的includeFilters和useDefaultFilters,则表示扫描该路径下的所有带注解的文件。
2、includeFilters为指定某种方式进行扫描,这里我采用了CUSTOM自定义扫描方式,根据CansluckTypeFilter配置进行扫描。includeFilters有以下几种扫描方式:
①、ANNOTATION,表示根据注解类型进行扫描,classes类型有:Controller.class、Service.cllass、Repository.class等,用ANNOTATION注解方式,必须添加classes扫描类型,否则将默认为不扫描任何注解,只会扫描这个配置文件的类,并且必须加上useDefaultFilters=false,useDefaultFilters默认为true,表示用默认的扫描,会扫描出全部,ANNOTATION不会生效。
②、ASPECTJ,表示根据ASPECTJ表达式扫描相匹配的类,并且useDefaultFilters=false,如果useDefaultFilters=true,则该配置不生效。(用得少就不介绍了)
③、ASSIGNABLE_TYPE,表示指定扫描某个接口派生出来的类,并且useDefaultFilters=false,如果useDefaultFilters=true,则该配置不生效。(用得少就不介绍了)
④、CUSTOM,表示扫描自定义的配置并实现了org.springframework.core.type.filter.TypeFilter接口的类,classes={实现了TypeFilter接口的类.class},并且useDefaultFilters=false,如果useDefaultFilters=true,则该配置不生效。
⑤、REGEX,表示扫描符合正则表达式的类,并且useDefaultFilters=false,如果useDefaultFilters=true,则该配置不生效。
关于Scope扫描规则
1、prototype:多实例,IOC容器启动的时候,IOC容器启动并不会去调用方法创建对象, 而是每次获取的时候才会调用方法创建对象
2、singleton:单实例(默认),IOC容器启动的时候会调用方法创建对象并放到IOC容器中,以后每次获取的就是直接从容器中拿(大Map.get)的同一个bean
3、request:主要针对web应用, 递交一次请求创建一个实例
4、session:同一个session创建一个实例
先来看看配置类
package com.blmyn.java.springtest.cap3.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.blmyn.java.springtest.cap1.Person;
/**
*
* @FileName Cap3MainConfig.java
* @Author xiaogaoxiang
* @At 2018年11月30日 上午9:51:00
* @Desc Scope扫描规则
*/
@Configuration
public class Cap3MainConfig {
// 给容器中注册一个bean, 类型为返回值的类型, 默认是单实例
/*
* 1、prototype:多实例: IOC容器启动的时候,IOC容器启动并不会去调用方法创建对象, 而是每次获取的时候才会调用方法创建对象
* 2、singleton:单实例(默认):IOC容器启动的时候会调用方法创建对象并放到IOC容器中,以后每次获取的就是直接从容器中拿(大Map.get)的同一个bean
* 3、request: 主要针对web应用, 递交一次请求创建一个实例
* 4、session:同一个session创建一个实例
*/
@Scope("prototype")
@Bean
public Person person() {
return new Person("xiaogaoxiang", 20);
}
}
看看多实例测试类结果:
package com.blmyn.java;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.blmyn.java.springtest.cap3.config.Cap3MainConfig;
public class Cap3Test {
@Test
public void test01() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap3MainConfig.class);
String[] names = app.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
// 其中Cap3MainConfig类中用了@Scope("prototype")多实例注解。
// 从容器中分别取两次person实例,看是否为同一个bean
Object bean1 = app.getBean("person");
Object bean2 = app.getBean("person");
System.out.println(bean1 == bean2);
}
}
控制台输出结果:
十一月 30, 2018 9:51:58 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3419866c: startup date [Fri Nov 30 09:51:58 CST 2018]; root of context hierarchy
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
cap3MainConfig
person
false
由此可见,用多实例的注解,表示当调用的时候才会去实例化对象,并且是分别初始化新的对象,因此两个bean1和bean2并不是同一个实例。Spring默认为单实例。
关于Lazy懒加载
先来看看配置类
package com.blmyn.java.springtest.cap4.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import com.blmyn.java.springtest.cap1.Person;
@Configuration
public class Cap4MainConfig {
// 给容器中注册一个bean, 类型为返回值的类型, 默认是单实例
/*
* 懒加载: 主要针对单实例bean:默认在容器启动的时候创建对象
* 懒加载:容器启动时候不创建对象,
* 仅当第一次使用(获取)bean的时候才创建被初始化
*/
@Lazy
@Bean
public Person person() {
System.out.println("给容器中添加person.......");
return new Person("xiaogaoxiang", 20);
}
}
这里增加了一个@Lazy注解,和单实例的bean的区别是:
1、单实例bean,默认在容器启动的时候创建对象
2、用懒加载,容器启动时候不创建对象
3、仅当第一次使用(获取)bean的时候才创建呗初始化
看看测试用例:
package com.blmyn.java;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.blmyn.java.springtest.cap4.config.Cap4MainConfig;
public class Cap4Test {
@Test
public void test01() {
@SuppressWarnings("resource")
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap4MainConfig.class);
System.out.println("IOC容器创建完成........");
app.getBean("person");// 执行获取的时候才创建并初始化bean
}
}
控制台输出结果:
十一月 30, 2018 9:58:21 上午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3419866c: startup date [Fri Nov 30 09:58:21 CST 2018]; root of context hierarchy
IOC容器创建完成........
给容器中添加person.......
我们可以看到控制台输出结果的先后顺序,用了@Lazy懒加载,并不会先创建Person的实例,而是当调用了之后,才会创建对象。如果没用懒加载,则会先把Person给创建,在输出“IOC容器创建完成”。
以上介绍了Spring项目简单搭建,相关扫描配置,配置类的一些介绍。