模拟Spring之Bean注解的应用

模拟Spring之应用Bean注解

上一篇文章是应用Compoent和Autowired注解实现类及其对象的注入工作。
那只是初步,现在考虑这种情况,对于一个已经打包成Jar包中的类,由于不能添加Compoent注解,应该如何实现注入呢?又或者,倘若一个不加Compoent注解的普通类,能不能同样实现类对象的注入工作?
解决方案:另外提供一个类,并在类中添加带Bean注解的方法实现注入。

首先构建作用于方法的Bean注解:

@Retention(RUNTIME)
@Target(METHOD)
public @interface Bean {
}

我事先准备了一个简单的类Complex,并将其打包成Jar包,另外准备一个Config类:

@Compoent
public class Config {

	public Config() {
	}
	
	@Bean
	public Complex getComplex() {
		System.out.println("这里通过Bean注解对Jar包中的类Complex进行注入!");
		Complex complex = new Complex();
		return complex;
	}

关于Bean注解的第一个应用场合:
之前的Autowired注解的缺陷是只能获取已经存储在容器中的对象,而容器中的对象对应的类都是加以Compoent注解的,而对于不可更改的Jar包中的类就不能加Compoent注解,也就不能实现对象的注入工作了。
Bean注解就解决了这一问题,通过给方法加Bean注解,将方法的返回值对象类型和返回值对象构建键值对,存储在Map中。

回想之前的BeanFactory的编写,对于类对象的实例化是直接通过klass.newInstance()来完成的,但对于Calendar类对象的实例化,是通过Calendar.getInstance()来实现的,基于这一情况,我想不更改BeanFactory的前提下,完成Calendar类对象的注入,同样在Config中给一个加Bean注解的方法就可以解决了。

	@Bean
	public Calendar getDate() {
		System.out.println("这里通过Bean注解对Calendar类对象进行注入!");
		Calendar date = Calendar.getInstance();
		return date;
	}

关于Bean注解的第二个应用场合:
若相关类没有提供可用的构造方法,包括构造方法是private的,相关构造方法不能直接调用,相关构造方法不能直接生成对象。对于这种情况下,由于对Compoent注解的处理是调用相关类的无参构造方法来获取类的对象的,所以上述情况下就不能产生类的对象了。
此时,就可以通过Bean注解,调用合适的获取类对象的方法,来得到类的对象并加入到Map中。

当然,我们也可以给一个类不加Compoent注解,而是通过Bean注解完成其对象的注入工作,

public class TwoClass {
	@Autowired
	private Complex complex;
	
	public TwoClass() {
	}

	@Override
	public String toString() {
		return "这是一个TwoClass类的对象!";
	}
	
}
	@Bean
	public TwoClass getTwoClass() {
		System.out.println("这里通过Bean注解对没有Compoent注解的类TwoClass进行注入!");
		TwoClass two = new TwoClass();
		return two;
	}

关于Bean注解的第三种应用场合:
相关类无参构造产生的对象不能直接使用。
通过Bean注解的方法,完成该对象所必须的基础数据,使得该对象可用。

处理Bean注解的方法

有了Config类中不同Bean注解的方法,我们在之前的BeanFactory类中只需添加一个处理Bean注解的方法即可。

	private static void dealBean(Class<?> klass, Object object) {
		Method[] methods = klass.getDeclaredMethods();
		for (Method method : methods) {
			if (!method.isAnnotationPresent(Bean.class)) {
				continue;
			}
			if (method.getParameterCount() > 0) {
				continue;
			}
			try {
				Class<?> returnType = method.getReturnType();
				Object value = method.invoke(object);
				
				BeanDefinition beanDefinition = new BeanDefinition();
				beanDefinition.setKlass(returnType);
				beanDefinition.setObject(value);
				beanDefinition.setSingleton(true);
				beanDefinition.setInject(false);
				
				classBeanPool.put(returnType.getName(), beanDefinition);
				showClassName();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
	}

该方法在扫描包过程中予以调用,因为相当于扫描到类Config并对其方法进行处理。
上面代码中的showClassName()方法是为了测试是否注入成功编写的,输出classBeanPool中的每一个键,即类名称。

测试结果看一下:

public class Test {

	public static void main(String[] args) {
		BeanFactory.scanPackage("com.mec.springioc.demo");
		BeanFactory beanFactory = new BeanFactory();
		
		OneClass one = beanFactory.getBean(OneClass.class);
		one.doSomething();
		System.out.println("Complex:" + one.getComplex());

		TwoClass two = beanFactory.getBean(TwoClass.class);
		System.out.println(two);
		
		
		ThreeClass three = beanFactory.getBean(ThreeClass.class);
		System.out.println(three.getTwo());

	}

}
这里通过Bean注解对Jar包中的类Complex进行注入!
com.mec.springioc.demo.Config
com.mec.complex.Complex
----------------------------
这里通过Bean注解对Calendar类对象进行注入!
com.mec.springioc.demo.Config
java.util.Calendar
com.mec.complex.Complex
----------------------------
这里通过Bean注解对没有Compoent注解的类TwoClass进行注入!
com.mec.springioc.demo.TwoClass
com.mec.springioc.demo.Config
java.util.Calendar
com.mec.complex.Complex
----------------------------
这是一个TwoClass类的对象!
Complex:Complex [real=0.0, vir=0.0]
这是一个TwoClass类的对象!
这是一个TwoClass类的对象!

从上述运行结果可以看出,通过Bean注解方法实现相应类对象的注入是成功的。

关于Bean注解的应用就简述至此,下一篇继续完善模拟Spring实现依赖注入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值