昨天从同事的分享那了解到Spring的大致结构,今天决定做一番总结。
一.创建maven工程项目

一路next,选择quickstart

next,输入Artifact Id,这个类似于安卓里面的工程名,finsh完成maven工程的创建

二.Maven工程结构

这里我们暂且只关注这三处文件
- App.java
该文件就是入口函数类,写过java的一目了然
package com.zsh.yhd.SpringProject;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
-
Maven Dependencies里面存放的是一些依赖库
-
pom.xml
这个文件可以理解成配置文件,我们可以在里面添加依赖库
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zsh.yhd</groupId>
<artifactId>SpringProject</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringProject</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
三.Spring配置
添加如下代码到上述的pom.xml中

配置完成之后我们的目录结构发生了一些变化,可以看到spring相关的库已被引入工程之中

四.开启Spring之旅
- Spring注入的两种方式
1. setter方式注入
2. 利用构造方式注入
First of all,我们来新建一个Book类
package com.zsh.yhd.SpringProject;
public class Book {
private String bookName;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
@Override
public String toString() {
return "Book [bookName=" + bookName + "]";
}
}
Book类有了,那么我们该怎么配置这个类呢,这时就需要引入一个新的文件applicationContext.xml放在resources目录下,如下图所示

来看下applicationContext.xml文件,很简单:
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
applicationContext.xml文件有了,下一步该是去写入配置来达到注入的目的了吧,没错,如下图,我们关注红圈内的部分

很明显可以看到配置了一个bean,我们为其设置了id,设置class了路径,这里的id先重点留意下,后面会使用到它。property中name和value分别对应Book类中的属性名和属性值
ok,到此为止,一个简单的Bean就配置完成,那么你可能在想,我们该怎么获取到Book实例,你可能采用这样传统的写法:
package com.zsh.yhd.SpringProject;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
Book book = new Book();
book.setBookName("xxxx");
}
}
然而,这不是我们想要的,我们得用高大上的方式--Spring
package com.zsh.yhd.SpringProject;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
// Book book = new Book();
// book.setBookName("xxxx");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Book book = (Book) applicationContext.getBean("mybook");
System.out.println(book);
}
}
首先通过ClassPathXmlApplicationContext加载上述所说的applicationContext.xml配置文件来获取到ApplicationContext实例,接下来我们就可以通过applicationContext.getBean的方式来获取具体的Bean实例,而getBean函数的参数mybook对应的其实就对应图8中的id,通俗的讲就是使用图8的bean来动态实例化Book类
运行查看结果:

通过查看日志发现Book类被实例化并且其属性值也没问题
讲了半天,上面这种通过property的方式其实就是上文所说的第一种注入方式,即setter方式注入
我们当然不能仅仅局限于一种方式(虽然第一种确实用的比较多),下面就来瞅瞅啥是构造方式注入,构造方式注入相对于setter方式较为复杂一点(但也就一点点),主要是因为其下又有两大分支:隐形注入和显性注入。
显而易见,从名字可以看出,不管是隐形注入还是显性注入,都得有个构造方法,OK,我们添加如下

当然,不可避免的,我们也需要修改applicationContext.xml文件
隐形方式修改如下:

显性方式修改如下:

App.java文件无需做任何改动,我们来试着运行下,没有任何问题

以上,便是Spring两种注入方式的简单使用,建议大家实际操作一遍,一目了然
- 有童鞋可能要说,你这也太简单了,都是一些基本数据类型,我想注入List怎么搞。
我们新建一个Student类文件
package com.zsh.yhd.SpringProject;
import java.util.List;
public class Student {
private int age;
private String name;
private List<String> cources;
public Student(int age, String name, List cources) {
super();
this.age = age;
this.name = name;
this.cources = cources;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getCources() {
return cources;
}
public void setCources(List cources) {
this.cources = cources;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + ", cources=" + cources + "]";
}
}
Student类里有三个属性,int类型的age,String类型的name,还有List<String>类型的cources,通过上文我相信你一定可以轻松加愉快的注入age和name了,下面就介绍如何注入cources吧
<!-- setter方式注入 -->
<bean id="myStudent" class="com.zsh.yhd.SpringProject.Student">
<property name="age" value="19"></property>
<property name="name" value="zsh"></property>
<property name="cources">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</property>
</bean>
<!-- 利用构造方式注入 -->
<bean id="myStudent" class="com.zsh.yhd.SpringProject.Student">
<!-- 隐形赋值 -->
<!-- <constructor-arg index="0" value="22"></constructor-arg>
<constructor-arg index="1" value="xyp"></constructor-arg>
<constructor-arg index="2">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</constructor-arg> -->
<!-- 显性设置 -->
<constructor-arg name="age" value="22"></constructor-arg>
<constructor-arg name="name" value="xyp2"></constructor-arg>
<constructor-arg name="cources">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</constructor-arg>
</bean>
到这里,我们停下脚步,自己对以上内容做下回顾,我只想强调一点,使用setter方式注入一定要写set方法,并且不能写构造方法;而使用构造方式注入必须写构造方法,set方法可写可不写,具体的大家可以自行去试试
- 看到这里,又有一些童鞋可能要搞事情了,你说的这些我都明白,但是我想注入另一个实例,怎么破,接着往下看*
修改Student文件如下:
package com.zsh.yhd.SpringProject;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
private int age;
private String name;
private List<String> cources;
@Autowired
private Book book;
public Student(int age, String name, List cources) {
super();
this.age = age;
this.name = name;
this.cources = cources;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + ", cources=" + cources + ", book=" + book + "]";
}
}
修改applicationContext.xml文件
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- setter方式注入 -->
<bean id="mybook" class="com.zsh.yhd.SpringProject.Book">
<property name="bookName" value="码农的一生"></property>
</bean>
<!-- 利用构造方式注入 -->
<bean id="myStudent" class="com.zsh.yhd.SpringProject.Student">
<!-- 隐形赋值 -->
<!-- <constructor-arg index="0" value="22"></constructor-arg>
<constructor-arg index="1" value="xyp"></constructor-arg>
<constructor-arg index="2">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</constructor-arg> -->
<!-- 显性设置 -->
<constructor-arg name="age" value="22"></constructor-arg>
<constructor-arg name="name" value="xyp2"></constructor-arg>
<constructor-arg name="cources">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</constructor-arg>
</bean>
<context:annotation-config />
<context:component-scan base-package="com.zsh.yhd.SpringProject" />
</beans>
这里停下需要了解几个概念
- <context:annotation-config/>
它的作用是隐式的向Spring容器注册
AutowiredAnnotationBeanPostProcessor,
CommonAnnotationBeanPostProcessor,
PersistenceAnnotationBeanPostProcessor,
RequiredAnnotationBeanPostProcessor
这4个BeanPostProcessor.注册这4个bean处理器主要的作用是为了你的系统能够识别相应的注解。
- 如果想使用@Autowired注解,需要在Spring容器中声明AutowiredAnnotationBeanPostProcessor Bean。传统的声明方式:<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
- 如果想使用@PersistenceContext注解,需要在Spring容器中声明PersistenceAnnotationBeanPostProcessor Bean。传统的声明:<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
- 如果想使用@Required注解,需要在Spring容器中声明RequiredAnnotationBeanPostProcessor Bean。传统声明方式:<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
- 如果想使用@Resource、@ PostConstruct、@ PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor。传统申明方式: <bean class="org.springframework.beans.factory.annotation.CommonAnnotationBeanPostProcessor"/>
所以,如果按照传统声明一条一条去声明注解Bean,就会显得十分繁琐。
因此如果在Spring的配置文件中事先加上<context:annotation-config/>这样一条配置的话,那么所有注解的传统声明就可以被忽略,即不用在写传统的声明,Spring会自动完成声明。
- <context:component-scan base-package="com.xx.xx" />
<context:component-scan/>的作用是让Bean定义注解工作起来,也就是上述传统声明方式。 它的base-package属性指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。
当我们获取Student实例的时候
我们发现了@Autowired注解作用在了book属性上,这样Spring就会去applicationContext.xml中扫描有没有类型为Book的bean,找到则依赖注入Student中book属性
- 可能又有人像我一样说,好烦啊,每次都要在applicationContext.xml中写bean的配置,有没有简单点的方式可以偷懒,答案是当然,针对这部分童鞋,我们使用终极武器--Component注解,参照如下
package com.zsh.yhd.SpringProject;
import org.springframework.stereotype.Component;
@Component
public class Book {
private String bookName;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
@Override
public String toString() {
return "Book [bookName=" + bookName + "]";
}
}
当Spring启动时,会扫描整个com.zsh.yhd.SpringProject包,当发现有@Component标注的类时,就会将它自动加入到Spring容器中。这样,@Autowired进行自动装配时,就可以找到对应的Bean了。
好了,今天就介绍到这,毕竟生活不止眼前的苟且,还有诗和远方的田野,我们学习完是不是应该来杯咖啡庆祝下😄
最后,附上我的Demo:https://github.com/zsh250663/SpringDemo
网友评论