前言
近期过年,在家待业,想闲着也是闲着,干脆充充电,撸撸Spring的源码玩玩,一提到Spring那么脑子里就会出现IOC和AOP
首先需要先搞定IOC,IOC先搞懂了,那么理解AOP就更加简单了!
IOC
概要
IOC大部分人都知道是容器,翻译过来是控制反转,也就是将我们手动创建Java对象的工作交给Spring来管理。
在我们写Java代码时需要new,我们需要什么对象new对象即可,这本身是没有什么问题,但是每次都要new的操作效率低,或者说new这个操作是有我们自己产生的,我们自己来产生这个new的操作,如我们需要10个对象,那么我们就需要new10次,需要100次我们就需要new100次,比较低效,那么我们可以将这个操作交给Spring来完成,那么也就是使用Spring IOC容器来完成。容器就是存放Java对象,也就是Bean,那么这些Bean就是存放在Java一些列的集合,如Map,List等 ,那么这里IOC容器底层实现原理实际上就是反射。通过反射实现@Autowired完成Bean的注入
反射
public class UserService {
}
public class UserController {
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
public class MyTestList {
@Test
public void test() throws Exception {
UserController userController=new UserController();
Class<? extends UserController> clazz = userController.getClass();
//创建对象
UserService userService = new UserService();
System.out.println(userService);
//获取属性
Field serviceField = clazz.getDeclaredField("userService");
serviceField.setAccessible(true);//设置为可访问私有属性
//只有通过方法才能够设置具体的属性值
String name = serviceField.getName();
//拼接方法的名称
name = name.substring(0, 1).toUpperCase() + name.substring(1, name.length());
String setMethodName = "set" + name;
//通过方法注入属性的对象--这里还没注入,只是在构建入参和需要执行的方法
Method method = clazz.getMethod("setUserService", UserService.class);
//反射--也就是执行ssetUserService这个方法
method.invoke(userController, userService);
System.out.println(userController.getUserService());
}
}
反射实现@Autowired
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Inherited/
@Documented
public @interface MyAutowired {
}
public class UserService {
}
public class UserController {
@MyAutowired
private UserService userService;
public UserService getUserService() {
return userService;
}
}
public class Test2 {
public static void main(String[] args) {
UserController userController=new UserController();
Class<? extends UserController> clazz = userController.getClass();
获取所有属性,并遍历
Stream.of(clazz.getDeclaredFields()).forEach(field->{
MyAutowired annotation = field.getAnnotation(MyAutowired.class);
if (annotation!=null){
field.setAccessible(true);
//得到属性的类型
Class<?> type = field.getType();
try {
//创建这个属性类型的对象
Object o = type.newInstance();
//设置属性值
field.set(userController,o);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
System.out.println(userController.getUserService());
}
}
上面演示两个反射的案例,现在回到IOC这部分,IOC是个容器,能够帮助我们来完成对象的整体创建,创建好之后我们直接在IOC这个容器中获取Java对象就可以了,通俗易懂的IOC就是我们获取具体对象的,这些对象简单的理解是存储在Map中,直接根据key获取Map中的value就可以了, 那么接下来我们看看他是如何将对象创建并存放到IOC中的!下面是大致流程图
-
上面xml、annotation这一组泛称BeanDefinition,BeanDefinition描述一个bean实例,该实例具有属性值、构造函数参数值和由具体实现提供的进一步信息。
-
通过这个BeanDefinitionReader接口将Bean读取到
BeanDefinition
进行存储
这里读取到Bean的信息后开始实例化,当然Spring不只是一个框架,更是一个生态,为了支撑更加灵活,高效的上层应用,对Spring而言,需要考虑更多的是扩展性,扩展性,扩展性,扩展性导致这里不能简单的直接实例化!
- Bean的对象创建时通过
BeanFunction
得到获取到BeanDefinition使用反射来创建的 BeanFactoryPostProcessor
,这个接口继承后就是来完成扩展操作的,如我们读取到Bean的时候,需要调用某个具体方法,那么我们就可以使用这个接口来完成实例化和初始化
,实例化就是调用对应的构造方法,然后开辟一块内存空间,但是里面的属性都没有完成赋值操作,那么在实例化完成之后需要完成一系列的初始化操作,那么在这实例化—>初始化—>初始化完成的阶段,那么就形成了AOP,其中也包括了BeanPostProcessor
这个接口Environment
这个接口中封装了一系列的系统环境值,代码中需要获取就直接调用即可
BeanFactory、FactoryBean区别
创建对象有两种方式,一种是BeanFactory,另一种是FactoryBean,一般情况下我们的常规对象都是用BeanFactory来完成创建的,某些特殊的对象,需要定制化的时候那么就需要采用FactoryBean来完成,那么在采用FactoryBean来实现的时候可以使用getObject来定制化处理,想怎么实现就怎么实现,feign就采用这种实现方式
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
TestMain testMain = new TestMain();
System.out.println("----------一系列而外的定制操作-----------");
//以直接通过getObject方法来完成定制化的Bran,无需使用BeanFactory一步一步按流程生成!
return testMain;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return true;
}
}