Bean
- 生命周期长
- 在整个虚拟机内可见
- 维护成本高,单例存在
优势
- 运行期效率高
- 统一维护,便于管理和扩展
Spring实现方式
- 包扫描并自动装配(反射)
- BeanFactory(统一管理)
- 依赖注入
依赖注入/控制反转
- IOC(Inversion Of Control):思想
- DI(Dependency Injection):方式
普通控制方式
普通控制方式.png
控制反转方式
控制反转.png
如何实现依赖注入
- 扫描包获得类定义(已达成)
- 初始化Bean,并实现依赖注入
- 解决Bean初始化顺序问题
依赖注入次序问题
依赖注入次序.png实现自己的依赖注入
- 创建注解@Bean、@AutoWried
package com.istimeless.beans;
import java.lang.annotation.*;
/**
* @author lijiayin
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AutoWired {
}
package com.istimeless.beans;
import java.lang.annotation.*;
/**
* @author lijiayin
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Bean {
}
- 创建BeanFactory
package com.istimeless.beans;
import com.istimeless.web.mvc.Controller;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author lijiayin
*/
public class BeanFactory {
private static Map<Class<?>, Object> classToBean = new ConcurrentHashMap<>();
public static Object getBean(Class<?> cls) {
return classToBean.get(cls);
}
/**
* 初始化Bean
* @param classList
* @throws Exception
*/
public static void initBean(List<Class<?>> classList) throws Exception {
List<Class<?>> toCreate = new ArrayList<>(classList);
while (toCreate.size() != 0){
int remainSize = toCreate.size();
for (int i = 0; i < toCreate.size(); i++) {
if(finishCreate(toCreate.get(i))){
toCreate.remove(i);
}
}
//没有任何对象被创建,循环引用
if(toCreate.size() == remainSize){
throw new Exception("cycle dependency!");
}
}
}
private static boolean finishCreate(Class<?> cls) throws IllegalAccessException, InstantiationException {
if(!cls.isAnnotationPresent(Bean.class)
&& !cls.isAnnotationPresent(Controller.class)){
return true;
}
Object bean = cls.newInstance();
for (Field field : cls.getDeclaredFields()){
if(field.isAnnotationPresent(AutoWired.class)){
Class<?> fieldType = field.getType();
Object reliantBean = BeanFactory.getBean(fieldType);
//对象还没创建,等待下一次循环创建
if(reliantBean == null){
return false;
}
field.setAccessible(true);
field.set(bean, reliantBean);
}
}
classToBean.put(cls, bean);
return true;
}
}
- 修改启动类,项目启动时加载类
package com.istimeless.starter;
import com.istimeless.beans.BeanFactory;
import com.istimeless.core.ClassScanner;
import com.istimeless.web.handler.HandlerManager;
import com.istimeless.web.server.TomcatServer;
import java.util.List;
/**
* @author lijiayin
*/
public class MiniApplication {
public static void run(Class<?> cls, String[] args){
System.out.println("Hello Mini-Spring!");
TomcatServer tomcatServer = new TomcatServer(args);
try {
tomcatServer.startServer();
List<Class<?>> classList = ClassScanner.scanClasses(cls.getPackage().getName());
//处理请求
HandlerManager.resolveMappingHandler(classList);
//初始化Bean
BeanFactory.initBean(classList);
classList.forEach(e -> System.out.println(e.getName()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 修改MappingHandler类,不需要创建Controller对象,直接从BeanFactory获取
package com.istimeless.web.handler;
import com.istimeless.beans.BeanFactory;
import lombok.AllArgsConstructor;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author lijiayin
*/
@AllArgsConstructor
public class MappingHandler {
/**
* 请求uri
*/
private String uri;
/**
* 请求方法
*/
private Method method;
/**
* 请求的类
*/
private Class<?> controller;
/**
* 请求的参数名
*/
private String[] args;
public boolean handle(ServletRequest req, ServletResponse res)
throws IllegalAccessException, InstantiationException,
InvocationTargetException, IOException {
String requestUri = ((HttpServletRequest) req).getRequestURI();
if(!uri.equals(requestUri)){
return false;
}
//获取参数
Object[] parameters = new Object[args.length];
for (int i = 0; i < args.length; i++) {
parameters[i] = req.getParameter(args[i]);
}
Object ctl = BeanFactory.getBean(controller);
Object response = method.invoke(ctl, parameters);
res.getWriter().println(response.toString());
return true;
}
}
- 创建SalaryService进行测试
package com.istimeless.service;
import com.istimeless.beans.Bean;
/**
* @author lijiayin
*/
@Bean
public class SalaryService {
public Integer calSalary(Integer experience){
return experience * 5000;
}
}
- 修改SalaryController,注入SalaryService
package com.istimeless.controller;
import com.istimeless.beans.AutoWired;
import com.istimeless.service.SalaryService;
import com.istimeless.web.mvc.Controller;
import com.istimeless.web.mvc.RequestMapping;
import com.istimeless.web.mvc.RequestParam;
/**
* @author lijiayin
*/
@Controller
@RequestMapping("/salary")
public class SalaryController {
@AutoWired
private SalaryService salaryService;
@RequestMapping("/getSalary.json")
public Integer getSalary(@RequestParam("name") String name,
@RequestParam("experience") String experience){
return salaryService.calSalary(Integer.parseInt(experience));
}
}
-
测试结果
测试结果.png
网友评论