需要研究定性一个小工程,所以需要复习一下spring,目前已经是spring5.0以上,java10以上,思维也已经变化了很多。最开始看了一些新特性基本是加强了注解,减少了配置文件,但个人需要宏观查看对象的依赖关系所以暂时还要看传统的配置文件方式,这样的方式我更认为老而弥坚。
下载Spring IDE: https://spring.io/tools/sts
选择的是Eclipse集合
首先新建三个maven工程:
work工程是父工程,管理依赖其实不用如下这么多,因为根据依赖传递只需要配置spring-context即可导入基本依赖包,但为了记住基本依赖所以全部加入,只是为了复习定性,工程版本管理没有借助源码管理工具,所以采用了最土的办法,只写了一个<user.pistachio.version>0.0.1-SNAPSHOT</user.pistachio.version>来定义版本,那么子工程也可以使用这个版本号,这样做会有警告,说maven今后不会支持,其实我用的就是最新的maven3.6,这样的提示不是一天两天了,
<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">
<properties>
<user.pistachio.version>0.0.1-SNAPSHOT</user.pistachio.version>
<spring.version>5.1.2.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>com.springstudy</groupId>
<artifactId>work</artifactId>
<version>${user.pistachio.version}</version>
<packaging>pom</packaging>
<modules>
<module>../springguides</module>
<module>../framework</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.springstudy</groupId>
<artifactId>framework</artifactId>
<version>${user.pistachio.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
两个子工程
<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">
<parent>
<groupId>com.springstudy</groupId>
<artifactId>work</artifactId>
<version>${user.pistachio.version}</version>
<relativePath>../work</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springguides</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>com.springstudy</groupId>
<artifactId>framework</artifactId>
</dependency>
</dependencies>
</project>
<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>
<parent>
<groupId>com.springstudy</groupId>
<artifactId>work</artifactId>
<version>${user.pistachio.version}</version>
<relativePath>../work</relativePath>
</parent>
<artifactId>framework</artifactId>
</project>
先在guides工程里写一个基本的登录行为类
package com.springstudy;
import com.springstudy.framework.Action;
import com.springstudy.framework.BasicMessage;
public class LoginAction implements Action {
private String name;
private String password;
private String pageUrl;
private int loginCnt;
private double netCoins;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPageUrl() {
return pageUrl;
}
public void setPageUrl(String pageUrl) {
this.pageUrl = pageUrl;
}
public int getLoginCnt() {
return loginCnt;
}
public void setLoginCnt(int loginCnt) {
this.loginCnt = loginCnt;
}
public double getNetCoins() {
return netCoins;
}
public void setNetCoins(double netCoins) {
this.netCoins = netCoins;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LoginAction(String name, String pageUrl, int loginCnt) {
super();
this.name = name;
this.pageUrl = pageUrl;
this.loginCnt = loginCnt;
System.out.println("[String,String,int构造函数初始化]"+this.toString());
}
public LoginAction(String name, String pageUrl, double netCoins) {
super();
this.name = name;
this.pageUrl = pageUrl;
this.netCoins = netCoins;
System.out.println("[String,String,double构造函数初始化]"+this.toString());
}
@Override
public String toString() {
return "LoginAction [name=" + name + ", password=" + password + ", pageUrl=" + pageUrl + ", loginCnt="
+ loginCnt + ", netCoins=" + netCoins + "]"+", HashCode [="+this.hashCode()+"]";
}
public LoginAction() {
System.out.println("无参数构造器开始初始化"+this.toString());
}
@Override
public BasicMessage execute(){
BasicMessage bm=BasicMessage.NONE;
if(name!=null && name.equals("admin")) {
bm=BasicMessage.SUCCESS;
return bm;
}
return bm;
}
}
上层framework工程:Action和基本消息枚举
package com.springstudy.framework;
public interface Action {
public BasicMessage execute();
}
package com.springstudy.framework;
public enum BasicMessage {
SUCCESS("成功", 1), NONE("无消息", 0),ERROR("错误", -1);
private String name;
private int index;
private BasicMessage(String name, int index) {
this.name = name;
this.index = index;
}
public static String getName(int index) {
for (BasicMessage c : BasicMessage.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
public String getName() {
return name;
}
public int getIndex() {
return index;
}
}
写上一个main类来写入口函数:
package com.springstudy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.springstudy.framework.Action;
public class Main {
public static void main(String[] args) {
// 传统方式,谁用对象就要创建它
LoginAction la = new LoginAction();
la.setName("admin");
System.out.println(la.execute().getName());
// Ioc控制容器负责创建对象,管理对象关系和对象生命周期,DI方式主要为约定实现方式,set,构造器,工厂注入三种方法。
// 控制反转是把创建任务交给容器,这样更符合自然,对象本来就存在,我们只是需要它一起协作来完成任务,更符合人类任务协作。
// 依赖注入,依赖谁注入?对于spring来说是依赖容器注入属性。
@SuppressWarnings("resource")
ApplicationContext ctx = new ClassPathXmlApplicationContext("App.xml");
Action springlact = ctx.getBean("loginAction", Action.class);
System.out.println(springlact.execute().getName());
//摆脱了对LoginAction的直接依赖,转变为对spring容器和数据(配置bean的id字面值)的依赖
ctx.getBean("loginAction1", Action.class);
ctx.getBean("loginAction2", Action.class);
ctx.getBean("loginAction3", Action.class);
ctx.getBean("loginAction4", Action.class);
}
}
然后是spring配置文件App.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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- set注入方式 -->
<bean id="loginAction" class="com.springstudy.LoginAction">
<property name="name" value="spring"></property>
</bean>
<!--采用LoginAction(String name, String pageUrl, int loginCnt)构造函数 -->
<bean id="loginAction1" class="com.springstudy.LoginAction">
<constructor-arg value="Tom"></constructor-arg>
<constructor-arg value="http://sc.skcompany"></constructor-arg>
<constructor-arg value="1"></constructor-arg>
</bean>
<!--采用LoginAction(String name, String pageUrl, double netCoins)构造函数 -->
<bean id="loginAction2" class="com.springstudy.LoginAction">
<constructor-arg index="0" value="Juidy"></constructor-arg>
<constructor-arg index="1" value="http://sc.skcompany"></constructor-arg>
<constructor-arg index="2" value="1.5"></constructor-arg>
</bean>
<!--采用LoginAction(String name, String pageUrl, double netCoins)构造函数 ,通过指定类型,这样字面值2不会使用int参数类型的构造函数 -->
<bean id="loginAction3" class="com.springstudy.LoginAction">
<constructor-arg index="0" value="Juidy"></constructor-arg>
<constructor-arg index="1" value="http://sc.skcompany"></constructor-arg>
<constructor-arg index="2" value="2" type="double"></constructor-arg>
</bean>
<!-- name方式,如果有特殊字符用CDATA方式,通过以上方式得出结论,如果含有多个构造函数的类,如果有类型歧义,那么不如使用如下方式或是set注入方式 -->
<bean id="loginAction4" class="com.springstudy.LoginAction">
<constructor-arg name="name" value="James"></constructor-arg>
<constructor-arg name="pageUrl">
<value><![CDATA[http://sc.skcompany]]></value>
</constructor-arg>
<constructor-arg name="netCoins" value="2"></constructor-arg>
</bean>
</beans>
这一次复习了,bean的set和构造方法注入属性方式,构造方法歧义的最佳思路,使用CDATA封装非法字符,确定了Ioc和DI的行为,概念上不能混为一谈,可能今后有更好的实现Ioc行为方式。