Spring IOC 在面试中经常出现的问题,通过刷面试题只能做到知其然不知其所以然,深入底层追问,然后就一脸懵逼,在此,手写一篇Spring IOC,帮你彻底理解什么叫控制反转
Spring IOC 操作有:配置文件方式,注解方式
本demo 采用注解方式:
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}
public interface BeanFactory {
/**
* 初始化 bean
*/
void initBeans() throws InstantiationException, IllegalAccessException;
/**
* 按 bean ID 获取 bean
* @param var1
* @return
*/
Object getBean(String var1) throws Exception;
/**
* 按 classes 获取 bean
* @param var1
* @param
* @return
*/
T getBean(Class var1);
}
public class ApplicationContext implements BeanFactory {
volatile int num;
/**
* 1. 定义一个bean容器,用于存放bean
* 2. 初始化 bean 并注入容器
* 3. 初始化 properties
*/
private String packageName;
/**
* 定义一个 bean 容器
*/
private ConcurrentHashMap
public interface OrderService {
void getOrder();
}
@Service
public class OrderServiceImpl implements OrderService {
@Override
public void getOrder() {
System.out.println(">>>>>>>>>>>>>>>>>>> 调用了 OrderServiceImpl.getOrder >>>>>>>>>>>>>>>>>>>>>>>>");
}
}
public interface UserService {
void findUserOrder();
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private OrderService orderServiceImpl;
@Override
public void findUserOrder() {
orderServiceImpl.getOrder();
}
}
public class ClassUtil {
public static List> getClass(String packageName) {
List> classes = new ArrayList<>();
boolean flag = true; //是否循环迭代
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String packagePath = packageName.replace(".", "/");
try {
Enumeration urls = classLoader.getResources(packagePath);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url == null) {
continue;
}
String protocol = url.getProtocol();
if ("file".equals(protocol)) {
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
findAndAddClassesInPackageByFile(packageName, filePath, flag, classes);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
private static void findAndAddClassesInPackageByFile(String packageName, String filePath, boolean flag, List> classes) {
File dir = new File(filePath);
if (!dir.exists() || !dir.isDirectory()) {
System.out.println("此路径下没有文件");
return;
}
File[] dirFiles = dir.listFiles(new FileFilter(){
@Override
public boolean accept(File pathname) {
return flag && pathname.isDirectory() || pathname.getName().endsWith(".class");
}
});
for (File file : dirFiles) {
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "/" + file.getName(), file.getAbsolutePath(), flag, classes);
} else {
String className = file.getName().substring(0, file.getName().length() -6);
System.out.println("类名:" +className);
try {
classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + "." + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
public class DemoTest {
public static void main(String[] args) throws Exception {
ApplicationContext app = new ApplicationContext("com.pro.service.impl");
UserServiceImpl userServiceImpl = (UserServiceImpl) app.getBean("userServiceImpl");
UserServiceImpl userService = app.getBean(UserServiceImpl.class);
userServiceImpl.findUserOrder();
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>");
userService.findUserOrder();
}
}