Spring学习(五)

简单手写Spring框架

1
2
3
4
5
6
7
8
9
package org.xiaoguan.core;

/**
* myspring框架应用上下文接口
*/
public interface ApplicationContext {
Object getBean(String beanName);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package org.xiaoguan.core;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext{
private static final Logger logger=LoggerFactory.getLogger(ClassPathXmlApplicationContext.class);
private Map<String,Object> singletonObject=new HashMap<>();
/**
* 解析mySpring的配置文件,然后初始化所有的bean对象
*/
private String configLocation;

public ClassPathXmlApplicationContext(String configLocation) {
try {
this.configLocation = configLocation;
SAXReader saxReader = new SAXReader();
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(configLocation);
Document document = saxReader.read(in);
List<Node> nodes = document.selectNodes("//bean");
nodes.forEach(node -> {
try {
Element beanElt = (Element) node;
String id = beanElt.attributeValue("id");
String clazz = beanElt.attributeValue("class");
Class<?> aClass = Class.forName(clazz);
Constructor<?> defaultCon = aClass.getDeclaredConstructor();
Object beanObject = defaultCon.newInstance();
singletonObject.put(id,beanObject);
logger.info(singletonObject.toString());
} catch (Exception e) {
e.printStackTrace();
}
});
nodes.forEach(node -> {
try {
Element beanElt = (Element) node;
String id = beanElt.attributeValue("id");
String className = beanElt.attributeValue("class");
Class<?> aClass = Class.forName(className);
List<Element> properties = beanElt.elements("property");
properties.forEach(property->{
try {
String name = property.attributeValue("name");
Field declaredField = aClass.getDeclaredField(name);
logger.info("属性名为:"+name);
String setMethodName="set"+name.toUpperCase().charAt(0)+name.substring(1);
Method setMethod = aClass.getDeclaredMethod(setMethodName,declaredField.getType());
String value = property.attributeValue("value");
String ref = property.attributeValue("ref");
logger.info("ref为:"+ref);
Object data=null;
if (value != null) {
String fieldSimpleName = declaredField.getType().getSimpleName();
switch (fieldSimpleName){
case "byte":
data = Byte.parseByte(value);
break;
case "short":
data=Short.parseShort(value);
break;
case "int":
data=Integer.parseInt(value);
break;
case "long":
data=Long.parseLong(value);
break;
case "float":
data=Float.parseFloat(value);
break;
case "double":
data=Double.parseDouble(value);
break;
case "boolean":
data= Boolean.parseBoolean(value);
break;
case "char":
data=value.charAt(0);
break;
case "Byte":
data = Byte.parseByte(value);
break;
case "Short":
data=Short.parseShort(value);
break;
case "Integer":
data=Integer.parseInt(value);
break;
case "Long":
data=Long.parseLong(value);
break;
case "Float":
data=Float.parseFloat(value);
break;
case "Double":
data=Double.parseDouble(value);
break;
case "Boolean":
data= Boolean.parseBoolean(value);
break;
case "Character":
data=value.charAt(0);
break;
default:
data=value;
}
setMethod.invoke(singletonObject.get(id),data);
}
if (ref != null) {
setMethod.invoke(singletonObject.get(id),singletonObject.get(ref));
}


} catch (Exception e) {
e.printStackTrace();
}
});
}catch (Exception e){
e.printStackTrace();
}

});
}catch (Exception e){
e.printStackTrace();
}
}

@Override
public Object getBean(String beanName) {
return singletonObject.get(beanName);
}
}

手写框架测试

1
2
3
4
5
6
7
8
package com.xiaoguan.bean;

public class OrderDao {
public void insert(){
System.out.println("myspring运行了");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.xiaoguan.bean;

public class OrderService {
private OrderDao orderDao;
public void generate(){
orderDao.insert();
}

public void setOrderDao(OrderDao orderDao) {
this.orderDao = orderDao;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.xiaoguan.bean;

public class Vip {
private String name;
private Integer age;
private double hight;

@Override
public String toString() {
return "Vip{" +
"name='" + name + '\'' +
", age=" + age +
", hight=" + hight +
'}';
}

public void setName(String name) {
this.name = name;
}

public void setAge(Integer age) {
this.age = age;
}

public void setHight(double hight) {
this.hight = hight;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>

<configuration>

<loggers>
<!--
level指定日志级别,从低到高的优先级:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
-->
<root level="INFO">
<appender-ref ref="spring6log"/>
</root>
</loggers>

<appenders>
<!--输出日志信息到控制台-->
<console name="spring6log" target="SYSTEM_OUT">
<!--控制日志输出的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
</console>
</appenders>

</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="vip" class="com.xiaoguan.bean.Vip">
<property name="name" value="小关"/>
<property name="age" value="23"/>
<property name="hight" value="1.63"/>
</bean>
<bean id="orderDao" class="com.xiaoguan.bean.OrderDao"/>
<bean id="orderService" class="com.xiaoguan.bean.OrderService">
<property name="orderDao" ref="orderDao"/>
</bean>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.xiaoguan.bean.OrderService;
import com.xiaoguan.bean.Vip;
import org.junit.Test;
import org.xiaoguan.core.ApplicationContext;
import org.xiaoguan.core.ClassPathXmlApplicationContext;

public class TestMySpring {
@Test
public void testMySpring(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("mySpring.xml");
Vip vip = (Vip) applicationContext.getBean("vip");
System.out.println(vip);
OrderService oderService = (OrderService) applicationContext.getBean("orderService");
oderService.generate();
}
}

注解式开发

1
2
3
4
5
6
7
8
package com.xiaoguan.bean;

import org.springframework.stereotype.Service;

@Service("orderBean")
public class Order {
}

1
2
3
4
5
6
7
8
package com.xiaoguan.bean;

import org.springframework.stereotype.Repository;

@Repository("studentBean")
public class Student {
}

1
2
3
4
5
6
7
8
9
package com.xiaoguan.bean;

import org.springframework.stereotype.Component;

@Component("userBean")
public class User {

}

1
2
3
4
5
6
7
8
package com.xiaoguan.bean;

import org.springframework.stereotype.Controller;

@Controller
public class Vip {
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.xiaoguan.bean2;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

@Component
public class A {
public A() {
System.out.println("A");
}
}
@Controller
class B{
public B() {
System.out.println("B");
}
}
@Service
class C{
public C() {System.out.println("C");
}
}
@Repository
class D{
public D() {System.out.println("D");
}
}
@Controller
class E{
public E() {System.out.println("E");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.xiaoguan.bean3;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
@Component
public class MyDataSource implements DataSource {
//使用value注解可以不用set方法
@Value("com.mysql.cj.jdbc.Driver")
private String driver;
@Value("jdbc:mysql:localhost:3306/spring6")
private String url;
@Value("root")
private String username;

@Override
public String toString() {
return "MyDataSource{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}

@Value("root")
private String password;

// public void setDriver(String driver) {
// this.driver = driver;
// }
//
// public void setUrl(String url) {
// this.url = url;
// }
//
// public void setUsername(String username) {
// this.username = username;
// }
//
// public void setPassword(String password) {
// this.password = password;
// }

@Override
public Connection getConnection() throws SQLException {
return null;
}

@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}

@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}

@Override
public void setLogWriter(PrintWriter out) throws SQLException {

}

@Override
public void setLoginTimeout(int seconds) throws SQLException {

}

@Override
public int getLoginTimeout() throws SQLException {
return 0;
}

@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}

@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}

@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.xiaoguan.bean3;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class User {

private String name;

private int age;
//value注解也可以用在方法上
// @Value("隔壁老王")
// public void setName(String name) {
// this.name = name;
// }
// @Value("30")
// public void setAge(int age) {
// this.age = age;
// }


public User(@Value("隔壁老王") String name,@Value("30") int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

1
2
3
4
5
6
7
8
9
10
package com.xiaoguan.bean4;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderDao {
void insert();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.xiaoguan.bean4.impl;

import com.xiaoguan.bean4.OrderDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository
public class OrderDaoImpltMysql implements OrderDao {
@Override
public void insert() {
System.out.println("Mysql数据库正在保存订单信息");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.xiaoguan.bean4.impl;

import com.xiaoguan.bean4.OrderDao;
import org.springframework.stereotype.Component;

@Component
public class OrderDaoImpltOracle implements OrderDao {
@Override
public void insert() {
System.out.println("Oracle数据库正在保存订单信息");
}
}

1
2
3
4
5
6
7
8
package com.xiaoguan.dao;

import org.springframework.stereotype.Component;

@Component
public class OrderDao {
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.xiaoguan.service;

import com.xiaoguan.bean4.OrderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
// @Qualifier("orderDaoImpltOracle")
@Qualifier("orderDaoImpltMysql")
@Autowired
private OrderDao orderDao;
public void generate(){
orderDao.insert();
}
}

1
2
3
4
5
6
7
8
9
package org.xiaoguan.dao;

import org.springframework.stereotype.Component;

@Component
public interface StudentDao {
void deletById();
}

1
2
3
4
5
6
7
8
9
10
11
12
package org.xiaoguan.dao.impl;

import org.springframework.stereotype.Component;
import org.xiaoguan.dao.StudentDao;
@Component
public class StudentDaoForMySql implements StudentDao {
@Override
public void deletById() {
System.out.println("MySql数据库正在删除学生信息");
}
}

1
2
3
4
5
6
7
8
9
10
package org.xiaoguan;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("org.xiaoguan")
public class Spring6Config {
}

1
2
3
4
5
6
7
8
9
10
<?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">
<!-- <context:component-scan base-package="com.xiaoguan.bean,com.xiaoguan.dao"/>-->
<!-- 可以指定父包,但是要牺牲一部分效率-->
<context:component-scan base-package="com.xiaoguan"/>
</beans>
1
2
3
4
5
6
7
8
<?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">
<context:component-scan base-package="com.xiaoguan.bean4,com.xiaoguan.service"/>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
<?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">
<!--
use-default-filters="false"表示所有的注解失效-->
<context:component-scan base-package="com.xiaoguan.bean2" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>
1
2
3
4
5
6
7
8
9
<?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">
<context:component-scan base-package="com.xiaoguan.bean3"/>

</beans>
1
2
3
4
5
6
7
8
<?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">
<context:component-scan base-package="org.xiaoguan"/>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.xiaoguan.test;

import com.xiaoguan.bean3.MyDataSource;
import com.xiaoguan.bean3.User;
import com.xiaoguan.service.OrderService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.xiaoguan.Spring6Config;
import org.xiaoguan.service.StudentService;

public class SpringAnnotationTest {
@Test
public void testNoXML(){
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Spring6Config.class);
StudentService studentService = annotationConfigApplicationContext.getBean("studentService", StudentService.class);
studentService.deleteStudent();
}
@Test
public void testResource(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-resource.xml");
StudentService studentService = applicationContext.getBean("studentService", StudentService.class);
studentService.deleteStudent();
}
@Test
public void testAutoWired(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-autowired.xml");
OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
orderService.generate();
}
@Test
public void testDIByAnnotation(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-DI-annotation.xml");
MyDataSource myDataSource = applicationContext.getBean("myDataSource", MyDataSource.class);
System.out.println(myDataSource);
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
@Test
public void testChoose(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-choose.xml0");
}
@Test
public void testSpringAnnotation(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
System.out.println(applicationContext.getBean("orderBean"));
System.out.println(applicationContext.getBean("studentBean"));
System.out.println(applicationContext.getBean("userBean"));
System.out.println(applicationContext.getBean("vip"));
System.out.println(applicationContext.getBean("orderDao"));
}
}