1.利用注解、反射和工厂模式设计一个简单的IoC容器。 2.该IoC容器包含3个注解和一个IoC容器类(AnnotationConfigApplicationContext),其定义如下。 注解 含义 @Component 标注Bean @Autowired 标注需要被注入的对象 @Configuration 标注为配置类 @ComponentScan 注解扫描器 3.自定义两个业务类Group和User,创建一个测试类Test,对IoC容器进行测试。
时间: 2024-03-26 22:34:29 浏览: 68
好的,我会根据你的要求进行回答。
首先,我们来看一下注解的定义:
@Component:用于标注一个类,表示该类是一个Bean,需要被IoC容器管理。
@Autowired:用于标注一个属性或者构造器,表示该属性或构造器需要被IoC容器注入一个Bean。
@Configuration:用于标注一个类,表示该类是一个配置类,其中定义的Bean会被IoC容器管理。
@ComponentScan:用于标注一个类,表示该类是一个注解扫描器,用于扫描并注册被@Component标注的类。
接下来,我们定义一个IoC容器类AnnotationConfigApplicationContext,该类用于管理IoC容器中的Bean:
```java
public class AnnotationConfigApplicationContext {
private Map<String, Object> beanMap = new HashMap<>();
public AnnotationConfigApplicationContext(Class<?> configClass) {
// 扫描配置类中的Bean
scan(configClass);
// 注册Bean
register();
}
// 扫描配置类中的Bean
private void scan(Class<?> configClass) {
// 获取@ComponentScan注解
ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
if (componentScan != null) {
// 获取扫描路径
String[] basePackages = componentScan.basePackages();
// 扫描路径下的所有类
for (String basePackage : basePackages) {
String path = basePackage.replace(".", "/");
URL url = getClass().getClassLoader().getResource(path);
if (url != null) {
File file = new File(url.getFile());
for (File f : file.listFiles()) {
String className = f.getName().replace(".class", "");
try {
Class<?> clazz = Class.forName(basePackage + "." + className);
if (clazz.isAnnotationPresent(Component.class)) {
// 注册@Component标注的Bean
register(clazz);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
}
// 注册Bean
private void register() {
for (Object bean : beanMap.values()) {
// 注入属性
inject(bean);
}
}
// 注册Bean
private void register(Class<?> clazz) {
try {
Object bean = clazz.newInstance();
beanMap.put(clazz.getSimpleName(), bean);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
// 注入属性
private void inject(Object bean) {
for (Field field : bean.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(Autowired.class)) {
Object fieldBean = beanMap.get(field.getType().getSimpleName());
if (fieldBean != null) {
try {
field.setAccessible(true);
field.set(bean, fieldBean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
// 获取Bean
public <T> T getBean(Class<T> clazz) {
return clazz.cast(beanMap.get(clazz.getSimpleName()));
}
}
```
然后,我们定义两个业务类Group和User:
```java
@Component
public class Group {
private String name;
public Group() {}
public Group(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
```java
@Component
public class User {
private String name;
private Group group;
public User() {}
public User(String name, Group group) {
this.name = name;
this.group = group;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}
```
最后,我们创建一个测试类Test,对IoC容器进行测试:
```java
@Configuration
@ComponentScan(basePackages = "com.example")
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
User user = context.getBean(User.class);
System.out.println(user.getName()); // 输出:张三
System.out.println(user.getGroup().getName()); // 输出:IT组
}
@Bean
public User user(Group group) {
return new User("张三", group);
}
@Bean
public Group group() {
return new Group("IT组");
}
}
```
以上就是一个简单的IoC容器的实现,通过注解、反射和工厂模式,我们可以实现依赖注入和Bean管理。
阅读全文