思考问题1
上面案例中,配置了@Component注解后,Spring是怎么知道这个类上有这个注解的?
思考问题2
没有使用new关键字,Spring是如何创建对象的?
思考问题3
Spring是如何将创建的对象注入到对应的属性中的?
6.2 IOC实现原理问题的答案是:通过反射机制+工厂模式实现
工厂模式是GOF23设计模式之一,主要封装JavaBean的创建过程
自定义注解
基本使用@Target(ElementType.值) //Target元注解 目标 值:FIELD 属性,METHOD 方法,TYPE 类、接口
@Retention(RetentionPolicy.值) //时机 值:SOURCE 源代码 ,RUNTIME 运行时
@documented
public @interface 注解名{
类型 方法名();
}
案例代码
1.自定义参数为字符串类型的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
//注入的值
String value();
}
2.自定义参数为引用类型的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
//注入的类型
Class value();
}
3.将Computer类注入装配到ioc容器里
public class Computer {
@MyValue("戴尔")
private String brand;
@MyComponent(IntelCpu.class)
private Cpu cpu;
@MyComponent(SumsungMemory.class)
private Memory memory;
...省略其余部分...
4.创建Computer的工厂对象(这里使用的是反射通过get,set方法初始化对象)
public class ComputerFactory {
public Computer createComputer(Class computerClass) throws Exception {
//反射创建对象
Object computer = computerClass.newInstance();
//遍历所有的属性
Field[] fields = computerClass.getDeclaredFields();
for(Field field : fields){
String fName = field.getName();
//读取自定义注解
MyValue myValue = field.getDeclaredAnnotation(MyValue.class);
if(myValue != null){
//通过反射调用set方法注入值
String mName = "set" + fName.substring(0,1).toUpperCase() + fName.substring(1);
Method set = computerClass.getDeclaredMethod(mName, field.getType());
set.invoke(computer,myValue.value());
}
MyComponent myComponent = field.getDeclaredAnnotation(MyComponent.class);
if(myComponent != null){
//通过反射调用set方法注入对象
String mName = "set" + fName.substring(0,1).toUpperCase() + fName.substring(1);
Method set = computerClass.getDeclaredMethod(mName, field.getType());
//通过配置的类型创建对象
Object obj = myComponent.value().newInstance();
set.invoke(computer,obj);
}
}
return (Computer) computer;
}
}
4.创建Computer的工厂对象(这里使用的是反射通过暴力访问属性的方法来初始化对象)
public class ComputerFactory {
public Computer creat(Class computerClass) throws InstantiationException, IllegalAccessException {
// 创建电脑对象
Object o = computerClass.newInstance();
// 获得所有属性
Field[] fields = computerClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
// 判断属性是否存在自定义注解
MyValue myValue = field.getDeclaredAnnotation(MyValue.class);
if (myValue != null){
// 将配置的属性赋值给对象
field.set(o,myValue.value());
System.out.println(myValue);
}
MyComponent myComponent = field.getDeclaredAnnotation(MyComponent.class);
if (myComponent != null){
// 将配置的属性赋值给对象
field.set(o,myComponent.value().newInstance());
}
}
return (Computer) o;
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
ComputerFactory computerFactory = new ComputerFactory();
Computer creat = computerFactory.creat(Computer.class);
creat.start();
}
}
5.代码测试
public class TestFactory {
public static void main(String[] args) {
ComputerFactory factory = new ComputerFactory();
try {
Computer computer = factory.createComputer(Computer.class);
computer.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}



