14.ioc中的annotation配置(注解)——@Component

知识点:
1) @Component使用之后需要在xml文件配置一个标签:`<context:component-scan/>`
2) @Component注解可以直接定义bean,而无需在xml定义bean。但是若两种定义同时存在,xml中的定义会覆盖类中注解的Bean定义(走无参构造)
3) @Component注解`直接写在类上面`即可
4) @Component如果`不指定参数,则bean的名称为当前类的类名首字母小写,其余的不变`
			@Component//相当于Boss boss=new Boss();
			public class Boss{
			}
5) @Component有一个`可选的参数,用于指定bean的名称`
			@Component("car1")//相当于Car car1=new Car();
			public class Car{
			}
			
			@Autowired
			@Qualifier("car1")//注入的是car1
			public class Boss{
				private Car car;
			}
6) <context:component-scan base-package="com.briup.ioc.annotation" /> 
   表示spring会检查`指定包下的java类,看它们是否使用了@Component注解`
7) @Component定义的bean默认情况下都是`单例模式`的,如果要让这个bean变为非单例,但是可以再结合这个@Scope注解来达到目标,@Scope("prototype")
@Component是Spring中所有bean组件的通用形式, 而@Repository @Service @Controller 
则是@Component的细化,用来表示更具体的用例,分别对应了持久化层、服务层和表现层。
但是至少到现在为止这个四种注解的实质区别很小(甚至几乎没有),都是把当前类注册为spring容器中的一个bean
注意:
	1.component-scan标签默认情况下自动扫描指定路径下的包(含所有子包)
	2.component-scan标签将带有@Component @Repository @Service @Controller注解的类自动注册到spring容器中
	3.component-scan标签对标记了@Required @Autowired @PostConstruct @PreDestroy @Resource @WebServiceRef @EJB   @PersistenceContext @PersistenceUnit等注解的类进行对应的操作,使注解生效
	4.`component-scan标签包含了annotation-config标签的作用`,所以只需要在xml文件中`只写<context:component-scan>,无需再写<context:annotation-config/>`

简单的大概例子:
@Component("car")
public class Car{ }

@Component("office")
public class Office{ }

@Component("boss")
public Boss{
	@Autowired
	private Car car;
	@Autowired
	private Office office;

	//假设直接从数据库中获得值,就不用再new对象了,因为已经走了无参构造new好了对象
	public void test(){
		car.setName("奥迪");
		office.setNum("002");
	}
}
再加上扫描注解的标签,当前内存中有了car对象,office对象,boss对象,对应的注入也没有问题
使用注解记得走无参构造器初始化对象`(要想给car里面加name值和price值,就必须用xml的配置文件,<bean>里面的<property>具体设置属性值)`

annotation.xml
只需要配置@component 初始化对象要用的context:component-scan和@Autowired 自动注入要用的context:annotation-config/

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
		    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		    xmlns:context="http://www.springframework.org/schema/context"
		    xsi:schemaLocation="
			   http://www.springframework.org/schema/beans 
			   http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
			   http://www.springframework.org/schema/context 
			   http://www.springframework.org/schema/context/spring-context-3.2.xsd">
 	<!-- @component 初始化对象要用的-->
	<context:component-scan base-package="com.briup.ioc.annotation" />
	<!-- @Autowired 自动注入要用的context:annotation-config被包含了,不需要写<context:annotation-config/>-->
</beans>

3个实体类

/com.briup.ioc.annotation.Office.java
package com.briup.ioc.annotation;
import org.springframework.stereotype.Component;

@Component
public class Office {
	private String num = "001";
	public Office(){	
	}	
	public Office(String num) {
		this.num = num;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
}
/com.briup.ioc.annotation.Car.java
package com.briup.ioc.annotation;
import org.springframework.stereotype.Component;

//@Component("car1")
@Component  //等同于Car car=new Car();等同于在配置文件中配置的bean
public class Car {
	private double price;
	private String name;
	public Car(){	
	}
	public Car(double price, String name) {
		this.price = price;
		this.name = name;
	}
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
/com.briup.ioc.annotation.Boss.java
package com.briup.ioc.annotation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Boss {
	private String name;
	@Autowired
	private Car car;
	@Autowired
	private Office office;
	
	public Boss(){
	}
	public Boss(String name, Car car, Office office) {
		this.name = name;
		this.car = car;
		this.office = office;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Car getCar() {
		return car;
	}
	
	public void setCar(Car car) {
		this.car = car;
	}
	public Office getOffice() {
		return office;
	}
	public void setOffice(Office office) {
		this.office = office;
	}
}

测试类:

@Test
//知识点: ioc中的注解
public void ioc_annotation() {
	try {
		String path = "com/briup/ioc/annotation/annotation.xml";
		ClassPathXmlApplicationContext container = new ClassPathXmlApplicationContext(path);
		Boss boss = (Boss) container.getBean("boss");
		System.out.println(boss);
		System.out.println(boss.getOffice());
		System.out.println(boss.getCar());
		container.destroy();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

结果:能够拿到对应的具体对象
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来设计一个简单的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()方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值