SpringIOC随笔(二)-仿写SpringIOC
SpringIOC随笔(二)-仿写SpringIOC
思路:
- 定义一个beanFactor工厂接口,提供getBean方法,
- 实现工厂,定义一个Bean容器,Map,为了实现线程安全,使用
private static Map<String, Object> beanMap = Collections.synchronizedMap(new HashMap<>());
- 初始化我们的bean容器,通过解析我们的xml配置文件
//beans/bean
创建出bean - 初始化完成bean容器后我们需要将bean之间的关系装配好(注入)
- 然后实现getBean方法。
使用技术:dom4j解析xml,反射
代码:
pom
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="userDaoHibernate" class="com.fxyh.spring.dao.impl.UserDaoHibernateImpl" />
<bean id="userDaoMybatis" class="com.fxyh.spring.dao.impl.UserDaoMybatisImpl"/>
<bean id="userService" class="com.fxyh.spring.service.impl.UserServiceImpl">
<property name="userDao" ref="userDaoMybatis" />
</bean>
</beans>
Dom4jUtils
public class Dom4jUtils {
/**
* @Author fengzhaoquan
* @Description 获取XML文档。其实就是将xml文档读取到内存中,形成DOM树
* @Date
* @Param
* @return
**/
public static Document getDocument(String fileName){
Document document = null;
if(StringUtils.isBlank(fileName)){
throw new IllegalArgumentException("");
}
try {
SAXReader reader = new SAXReader();
document = reader.read(Dom4jUtils.class.getClassLoader().getResourceAsStream(fileName));
} catch (DocumentException e) {
e.printStackTrace();
}
return document;
}
}
BeanFactory接口
public interface BeanFactory {
/**
* @Author fengzhaoquan
* @Description 实现了该接口类型的对象
* @Param clazz 接口类型的对象
**/
Object getBean(Class clazz);
/**
* @Author fengzhaoquan
* @Description 获取className的对象(id)
**/
Object getBean(String className);
}
ClassPathXmlApplicationContext实现BeanFactory接口
/**
* @ClassName: ClassPathXmlApplicationContext
* @description: BeanFactory的一个实现类
* 1. 将xml中所有的bean标签创建出对象,然后放入容器中
* 2. 对外提供了getBean方法,从而对于客户端而言可以很轻松的获取对象
* @author: fengzhaoquan
* @create: 2019-06-16 16:44
* @Version 1.0
**/
public class ClassPathXmlApplicationContext implements BeanFactory {
/**
* @Author fengzhaoquan
* @Description 配置文件中所有的bean都会放入beanMap中
**/
private static Map<String, Object> beanMap = Collections.synchronizedMap(new HashMap<>());
public ClassPathXmlApplicationContext() {
this("applicationContext.xml");
}
public ClassPathXmlApplicationContext(String fileName) {
if (StringUtils.isBlank(fileName)) {
throw new IllegalArgumentException("");
}
try {
// 解析XML
// 初始化beanMap
initBeanMap(fileName);
// 将bean之间的关系装配好(注入)
injection(fileName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @Author fengzhaoquan
* @Description 将bean之间的关系装配好(注入)
**/
private void injection(String fileName) throws Exception {
Document document = Dom4jUtils.getDocument(fileName);
List<Element> propertyElementList = document.selectNodes("//beans/bean/property");
if (CollectionUtils.isNotEmpty(propertyElementList)) {
for (Element propertyElement : propertyElementList) {
String name = propertyElement.attributeValue("name");
String refValue = propertyElement.attributeValue("ref");
//setXxx方法拼接
String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
//找到父元素,也是就要被注入的对象
Element beanElement = propertyElement.getParent();
String parentElementIdValue = beanElement.attributeValue("id");
if (beanMap.containsKey(parentElementIdValue) && beanMap.containsKey(refValue)){
Object targetObject = beanMap.get(parentElementIdValue);
Object parameterValue = beanMap.get(refValue);
Method method = targetObject.getClass().getDeclaredMethod(methodName, parameterValue.getClass().getInterfaces());
method.invoke(targetObject, parameterValue);
}
}
}
}
/**
* @Author fengzhaoquan
* @Description 初始化beanMap
**/
private void initBeanMap(String fileName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Document document = Dom4jUtils.getDocument(fileName);
//XPath
List<Element> beanElementList = document.selectNodes("//beans/bean");
if (CollectionUtils.isNotEmpty(beanElementList)) {
for (Element beanElement : beanElementList) {
String id = beanElement.attributeValue("id");
String beanClassName = beanElement.attributeValue("class");
beanMap.put(id, Class.forName(beanClassName).newInstance());
}
}
}
@Override
public Object getBean(Class clazz) {
if(clazz == null){
throw new IllegalArgumentException("");
}
return beanMap.get(clazz.getSimpleName().substring(0,1).toLowerCase() + clazz.getSimpleName().substring(1));
}
@Override
public Object getBean(String className) {
if(StringUtils.isBlank(className)){
throw new IllegalArgumentException("");
}
return beanMap.get(className);
}
}
Service,Dao,model代码:
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void addUser(User user) {
userDao.addUser(user);
}
}
public class UserDaoHibernateImpl implements UserDao {
@Override
public void addUser(User user) {
System.out.println("Hibernate add:" + user);
}
}
public class UserDaoMybatisImpl implements UserDao {
@Override
public void addUser(User user) {
System.out.println("Mybatis add:" + user);
}
}
public class User implements Serializable {
private static final long serialVersionUID = -5333671573596770181L;
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
单元测试
public class UserServiceImplTest {
private BeanFactory factory;
private UserService userService;
@Before
public void setUp() throws Exception {
this.factory = new ClassPathXmlApplicationContext();
this.userService = (UserService) this.factory.getBean(UserService.class);
}
@Test
public void addUser() {
User user = new User();
user.setName("zhangsan");
user.setPassword("123456");
userService.addUser(user);
}
}
还没有评论,来说两句吧...