@Component和@Configuration注解的区别
时间: 2023-05-14 12:07:26 浏览: 105
@Component 和 @Configuration 注解的区别在于,@Component 是用来标识一个类为组件,可以被 Spring 自动扫描并装配到容器中,而 @Configuration 则是用来标识一个类为配置类,其中可以定义一些 Bean 的创建和配置方法,这些 Bean 也可以被 Spring 自动扫描并装配到容器中。另外,@Configuration 还可以用来定义一些配置属性和配置方法,用于配置整个应用程序的行为。
相关问题
@Configuration 和 @Component 注解的区别
@Configuration 和 @Component 注解的区别主要在于它们的作用和使用场景不同。
@Configuration 注解表示这是一个配置类,通常用于定义应用程序的配置信息,包括配置数据源、配置 Bean、配置拦截器等等。配置类中的方法通常使用 @Bean 注解来声明一个 Bean。
而 @Component 注解表示这是一个组件类,通常用于定义应用程序中的一个组件,例如 Service、Controller、Repository 等等。组件类中的方法通常不会返回一个 Bean,而是通过 @Autowired 注解来依赖注入其他 Bean。
总的来说,@Configuration 注解用于定义配置类,@Component 注解用于定义组件类。但是这两个注解也有一定的交叉使用场景。比如一个组件类可以通过 @Configuration 注解来声明一些 Bean,或者一个配置类中的方法也可以使用 @Component 注解来声明一个组件类。
利用注解、反射和工厂模式设计一个简单的IoC容器,该IoC容器包含注解 @Component @Autowired @Configuration @ComponentScan和一个IoC容器类AnnotationConfigApplicationContext
好的,我来设计一个简单的IoC容器。
首先,我们需要定义注解:
```java
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
String value() default "";
}
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Configuration {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String[] value() default {};
}
```
这里定义了四个注解,分别是@Component、@Autowired、@Configuration和@ComponentScan。
@Component表示该类是一个组件,需要被IoC容器管理。
@Autowired表示该属性需要被自动注入。
@Configuration表示该类是一个配置类,用于配置IoC容器。
@ComponentScan表示需要扫描的包路径。
接下来,我们定义一个IoC容器类:
```java
public class AnnotationConfigApplicationContext {
private Map<String, Object> beans = new HashMap<>(); // 存储所有的bean
private Map<Class<?>, Object> configurationBeans = new HashMap<>(); // 存储所有的@Configuration类
private Set<Class<?>> componentClasses = new HashSet<>(); // 存储所有的@Component类
public AnnotationConfigApplicationContext(Class<?> configurationClass) {
scan(configurationClass);
registerBeans();
autowireBeans();
}
private void scan(Class<?> configurationClass) {
ComponentScan componentScan = configurationClass.getAnnotation(ComponentScan.class);
if (componentScan != null) {
String[] basePackages = componentScan.value();
for (String basePackage : basePackages) {
Set<Class<?>> classes = ClassScanner.getClasses(basePackage);
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(Component.class)) {
componentClasses.add(clazz);
}
}
}
}
}
private void registerBeans() {
for (Class<?> clazz : componentClasses) {
Object bean = createBean(clazz);
beans.put(clazz.getName(), bean);
}
for (Class<?> clazz : configurationBeans.keySet()) {
Object bean = configurationBeans.get(clazz);
beans.put(clazz.getName(), bean);
}
}
private Object createBean(Class<?> clazz) {
try {
Object instance = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
String beanName = field.getType().getName();
Object bean = beans.get(beanName);
if (bean == null) {
throw new RuntimeException("Can not find bean: " + beanName);
}
field.setAccessible(true);
field.set(instance, bean);
}
}
return instance;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Create bean failed: " + clazz.getName());
}
}
private void autowireBeans() {
for (Object bean : beans.values()) {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
String beanName = field.getType().getName();
Object autowiredBean = beans.get(beanName);
if (autowiredBean == null) {
throw new RuntimeException("Can not find bean: " + beanName);
}
field.setAccessible(true);
try {
field.set(bean, autowiredBean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
public <T> T getBean(Class<T> clazz) {
Object bean = beans.get(clazz.getName());
if (bean == null) {
throw new RuntimeException("Can not find bean: " + clazz.getName());
}
return (T) bean;
}
public <T> T getBean(String beanName) {
Object bean = beans.get(beanName);
if (bean == null) {
throw new RuntimeException("Can not find bean: " + beanName);
}
return (T) bean;
}
}
```
这个IoC容器类包含了三个方法:scan()、registerBeans()和autowireBeans()。
scan()方法用于扫描所有的@Component类,并将它们保存到componentClasses中。
registerBeans()方法用于创建所有的bean,并将它们保存到beans中。
autowireBeans()方法用于自动注入所有的bean。
最后,我们定义一个测试类:
```java
@Configuration
@ComponentScan({"com.example.demo"})
public class AppConfig {
}
@Component
public class UserDao {
public void save() {
System.out.println("Save user");
}
}
@Component
public class UserService {
@Autowired
private UserDao userDao;
public void save() {
userDao.save();
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
userService.save();
}
}
```
这个测试类中,我们定义了一个@Configuration类AppConfig,用于配置IoC容器,并指定需要扫描的包路径。
另外,我们定义了一个UserDao类和一个UserService类,它们都被标注为@Component,表示需要被IoC容器管理。
在UserService类中,我们使用@Autowired注解自动注入UserDao对象。
最后,在main()方法中,我们创建了一个AnnotationConfigApplicationContext对象,并传入AppConfig.class作为构造函数参数。然后,我们从容器中获取UserService对象,并调用它的save()方法。
阅读全文