类的说明:
- Address、Customer、Order类是普通的bean类
- Config类可以理解为Spring中添加了@Configuration的类
- Container类可以理解为Spring中的容器
- 重点在于Container类,其中的属性和方法在代码块中添加了注释
在Spring中,对bean的注入基本方式有两种,一是我们自己项目中的类,添加了如@Component注解的方式;二是添加了@Configuration搭配@Bean的方式
这个小示例就演示了这两种方式注入的基本原理。其中Container类中的getServiceInstanceByClass()演示了方法二的基本实现;createInstance()演示了方法一的基本实现,且有一个Autowired注入的演示。
很多反射的使用,注解本质上就是一个标记,除此之外没有任何意义,有意义的在于处理该标记的方法。
java
public class Address {
private String street;
private String postCode;
public void printStreet() {
System.out.println("Address street: " + street);
}
public void printPostCode() {
System.out.println("Address postCode: " + postCode);
}
}
java
public class Customer {
private String name;
private String email;
public void printName() {
System.out.println("Address street: " + name);
}
public void printEmail() {
System.out.println("Address postCode: " + email);
}
}
java
public class Order {
private Customer customer;
private Address address;
public Order() {
}
@Autowired
public Order(Customer customer, Address address) {
this.customer = customer;
this.address = address;
}
}
java
/**
* 配置类,类比Spring中添加了Configuration注解的类
*/
public class Config {
@Bean
public Customer customer(){
return new Customer();
}
@Bean
public Address address(){
return new Address();
}
public Message message(){
return new Message();
}
}
java
/**
* 模拟Spring的容器
*/
public class Container {
//该map存储的是配置类中的所有方法,作用是通过method创建实例对象,见getServiceInstanceByClass方法
private Map<Class<?>, Method> methods;
private Object config;
// 该map是存储已经实例化成功的bean
private Map<Class<?>, Object> service;
/**
该方法的作用是初始化配置类,以及将配置类中的所有method存储到容器的methods map中
*/
public void init() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
this.methods = new HashMap<>();
this.service = new HashMap<>();
Class<?> clazz = Class.forName("Reflection.Config");
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(Bean.class)) {
this.methods.put(method.getReturnType(), method);
}
}
this.config = clazz.getConstructor().newInstance();
}
/**
* 该方法的作用是通过class获得容器中已经实例化成功的对象
* 双重锁检测
*/
public Object getServiceInstanceByClass(Class<?> clazz) throws InvocationTargetException, IllegalAccessException {
if (this.service.containsKey(clazz)) {
return this.service.get(clazz);
}
synchronized (Container.class){
if (this.service.containsKey(clazz)) {
return this.service.get(clazz);
}
if (this.methods.containsKey(clazz)) {
Method method = this.methods.get(clazz);
Object obj = method.invoke(this.config);
this.service.put(clazz,obj);
return obj;
}
}
return null;
}
/**
*该方法的作用是通过class参数创建一个该类型的对象
*/
public Object createInstance(Class<?> clazz) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for(Constructor<?> constructor : constructors){
if(constructor.getDeclaredAnnotation(Autowired.class) != null){
Class<?>[] parameterTypes = constructor.getParameterTypes();
Object[] arguments = new Object[parameterTypes.length];
for(int i = 0; i < parameterTypes.length; i++){
arguments[i] = getServiceInstanceByClass(parameterTypes[i]);
}
return constructor.newInstance(arguments);
}
}
// 如果没有@Autowired注解,就创建一个无参构造函数的实例
return clazz.getConstructor().newInstance();
}
}
java
public class Main {
public static void main(String[] args) throws Exception {
Container container = new Container();
container.init();
Class<?> clazz = Class.forName("Reflection.Order");
Object obj = container.createInstance(clazz);
Field filed = clazz.getDeclaredField("customer");
filed.setAccessible(true);
Object fieldValue = filed.get(obj);
Method[] declaredMethods = fieldValue.getClass().getDeclaredMethods();
for (Method method : declaredMethods){
System.out.println(method.getName());
method.invoke(fieldValue);
}
}
}