spring底层原理解析
Bean创建的生命周期
UserService-->无参构造(推断构造方法)-->普通对象-->依赖注入-->初始化前(@PostConstruct)-->初始化(InitializingBean)-->初始化后(AOP)-->代理对象-->完整的Bean
判断是否要进行生成代理对象
1.找出所有的切面Bean
2.遍历所有的切面方法
3.缓存到map,在哪个类型的对象上进行切入,切入的方法
4.判断当前创建的对象,是否有切面的缓存,如果有则执行的时候,从缓存中拿到切面的方法,来执行
UserServiceProxy-->代理对象-->代理对象.target=被代理的普通对象(之前被注入的普通对象)
无参构造(推断构造方法)
spring默认通过无参构造来初步构建对象,当然,当只有一个有参构造的时候,会用这一个有参,但是当多个有参构造的时候就需要声明用哪一个了,也就是spring会根据当前类的所有的构造方法,来判断用哪一个,判断不了的时候就需要认为设置;
@Component public class UserService implements InitializingBean { private OrderService orderService; private String s; public void doSomething(){ System.out.println("do"); } @PostConstruct public void a(){ //从数据库中给orderService赋值 } public void afterPropertiesSet() throws Exception { //从数据库中给orderService赋值 } /* public UserService() { }*/ public UserService(OrderService orderService) { this.orderService = orderService; } @Autowired //此时就需要声明构造方法 public UserService(OrderService orderService, String s) { this.orderService = orderService; this.s = s; } }
依赖注入
依赖注入的引入:
@Component public class UserService { @Autowired private OrderService orderService; public void doSomething(){ System.out.println("do"); } }
引用
public class SpringStater { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); //容器获得对象 UserService userService = context.getBean(UserService.class); //自己new的对象 UserService userService1 = new UserService(); //区别在于,通过容器拿到的对象userService中orderService有值,而自己创建出来的userService1中orderService为空,而在UserService.calss中,只有一个默认的空参构造,所以肯定spring最开始也是调用空参构造,后续的操作让对象中有了orderService(依赖注入) //比如 通过声明的注解来进行设置 for (Field field : userService1.getClass().getFields()) { if(field.isAnnotationPresent(Autowired.class)){ field.set(userService1,"orderService"); } } } }
初始化前(@PostConstruct)-->初始化(InitializingBean)
比如上面的的orderservice是需要从数据库查询得到,也就是说我们需要在正式成为Bean之前,就调用a方法,那么我们就要告知spring来做处理
方式1 @PostConstruct;
方式2 InitializingBean--afterPropertiesSet
方式3 AOP来生成代理对象
@Component public class UserService implements InitializingBean { @Autowired private OrderService orderService; public void doSomething(){ System.out.println("do"); } @PostConstruct public void a(){ //从数据库中给orderService赋值 } public void afterPropertiesSet() throws Exception { //从数据库中给orderService赋值 } }
注入的时候,先根据类型去查找,然后根据名字匹配;当找到的对象不唯一或者找不到的时候就会报错
初始化后(AOP)
spring的动态代理使用的CGlib,用的是继承
切面
@Component @Aspect public class UserAspect { @Before("execution( public void com.chenlei.pojo.UserService.doSomething())") public void userBefore(JoinPoint joinPoint){ System.out.println("before"); } }
配置类开启切面
@ComponentScan("com.chenlei") @EnableAspectJAutoProxy public class MyConfig { }
真正执行时,有值
代理类似以下
public class UserServiceProxy extends UserService { //其实这里创建的代理对象,虽然都有这些属性,但是spring的bean的生命周期中,它的AOP之后,并没有对代理对象进行依赖注入,代理对象的属性值为空,所以它其实是在创建代理对象的时候,把之前创建的普通对象给到代理对象,调用doSomething方法时,用的是之前的普通对象target,target是在之前进行了注入的,所以它的OrderService有值 private UserService target; @Override public void doSomething() { //执行@before //最终是普通对象执行doSomething target.doSomething(); } }
spring事务
spring事务失效的问题,
*/ @Component public class UserService implements InitializingBean { @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void test(){ jdbcTemplate.execute("insert t1 values (1,1,1,1)"); b(); } @Transactional(propagation = Propagation.NEVER)//只能在不存在事务的时候执行 public void b(){ jdbcTemplate.execute("insert t1 values (2,2,2,2)"); } }
此时,我们插入1数据的时候,按理来说,我们是不能进行数据2的插入,因为数据2添加了Propagation.NEVER;
但实际情况是我们执行成功了
public class UserServiceProxy extends UserService { private UserService target; @Override public void doSomething() { //获取链接 //关闭自动提交 //普通对象执行test target. test();-->b()是target普通对象在执行,没有代理对象 因此不存在spring事务 } }
原因是因为在数据1test()这里开启了事务,但是这个事务是开启在代理对象上的,而代理对象在执行test方法时,先去执行了,获取链接,关闭自动提交,当执行到test()时,是原来的普通对象在执行,也就是说 b();也是普通对象在执行,所以事务就失效了(而spring事务生效的关键就是代理对象来控制了非自动提交),所以解决办法是,在当前对象中,注入自己(这里的自己其实就是代理对象),同样用代理对象来执行,事务就会生效
@Component public class UserService implements InitializingBean { @Autowired //注入代理对象 private UserService userService; @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void test(){ jdbcTemplate.execute("insert t1 values (1,1,1,1)"); userService.b(); } @Transactional(propagation = Propagation.NEVER)//只能在不存在事务的时候执行 public void b(){ jdbcTemplate.execute("insert t1 values (2,2,2,2)"); } }
手写一个简单的spring
1.创建我们的applicationContext
public class ChenLeiApplicationContext {
//配置类
private Class clazz;
private Map<String,ChenLeiBeanDefinition> beanDefinitionMap = new HashMap<String, ChenLeiBeanDefinition>();
//单例池
private Map<String,Object> singletonBeanMap = new HashMap<String, Object>();
private List<ChenLeiBeanPostProcessor> processorList=new ArrayList<ChenLeiBeanPostProcessor>();
public ChenLeiApplicationContext(Class configClazz) {
//配置类 定义了bean扫描路径
this.clazz = configClazz;
//根据扫描路径进行扫描
scan(configClazz);
//开始创建单例对象 找到beanDefinitionMap中为单例的
for (Map.Entry<String, ChenLeiBeanDefinition> entry : beanDefinitionMap.entrySet()) {
//只要不是原型 是单例就创建
if (!"prototype".equals(entry.getValue().getScope())) {
Object bean = createBean(entry.getKey(), entry.getValue());
singletonBeanMap.put(entry.getKey(),bean);
}
}
}
private void scan(Class configClazz) {
//扫描类路径 获取当前clazz扫描路径
if (configClazz.isAnnotationPresent(ChenLeiComponentscan.class)) {
ChenLeiComponentscan componentscanAnnotation = (ChenLeiComponentscan)configClazz.getAnnotation(ChenLeiComponentscan.class);
//定义的扫描的路径
String path = componentscanAnnotation.value().replace(".","/");
ClassLoader classLoader = ChenLeiApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
//如果是一个文件夹
if (file.isDirectory()) {
for (File f : file.listFiles()) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class")).replace("\\", ".");
Class<?> aClass = null;
try {
aClass = classLoader.loadClass(absolutePath);
if (aClass.isAnnotationPresent(ChenLeiComponent.class)) {
//在扫描的时候就把processor 创建 并缓存起来 方便 创建bean用
//判断aClass类是否是ChenLeiBeanPostProcessor
if (ChenLeiBeanPostProcessor.class.isAssignableFrom(aClass)) {
ChenLeiBeanPostProcessor instance = (ChenLeiBeanPostProcessor)aClass.getConstructor().newInstance();
processorList.add(instance);
continue;
}
ChenLeiBeanDefinition beanDefinition = new ChenLeiBeanDefinition();
//我们定义的beanName
String beanName = aClass.getAnnotation(ChenLeiComponent.class).value();
//JDK提供的获取类的首字母小写
if("".equals(beanName)){
beanName = Introspector.decapitalize(aClass.getSimpleName());
}
beanDefinition.setaClass(aClass);
if (aClass.isAnnotationPresent(ChenLeiScope.class)) {
//设置我们配置的值
String value = aClass.getAnnotation(ChenLeiScope.class).value();
beanDefinition.setScope(value);
}else {
//不配置默认单例
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
public Object getBean(String beanName){
//如果beanDefinitionMap没有这个key 则说明当前容器中没有定义一个这样的bean
if (!beanDefinitionMap.containsKey(beanName)) {
return new NullPointerException();
}else {
ChenLeiBeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if("singleton".equals(beanDefinition.getScope())){
Object singletonBean= singletonBeanMap.get(beanName);
//beanDefinition的创建是在创建bean之前做的,所以只要是定义了的bean beanDefinition中都会有
//但是容器中的bean是一个一个创建的,所以当A需要B的时候,B可能还没有被创建
if (singletonBean==null) {
singletonBean = createBean(beanName, beanDefinition);
singletonBeanMap.put(beanName,singletonBean);
}
//单例从容器中拿
return singletonBean;
}else {
//原型(多例)直接根据beanName和beanDefinition创建
return createBean(beanName,beanDefinition);
}
}
}
public Object createBean(String beanName,ChenLeiBeanDefinition beanDefinition){
Class aClass = beanDefinition.getaClass();
Object bean=null;
try {
//这里spring 会去推断使用哪一个构造方法 我们简单使用无参构造
bean = aClass.getConstructor().newInstance();
//根据属性的名来进行注入
for (Field field : aClass.getFields()) {
if (field.isAnnotationPresent(ChenLeiAutowired.class)) {
field.setAccessible(true);
field.set(bean,getBean(field.getName()));
}
}
//初始化前
for (ChenLeiBeanPostProcessor processor : processorList) {
//aop 一般在这里使用 cglib来创建代理对象 所以原来的bean就是代理对象
bean = processor.postProcessBeforeInitialization(bean, beanName);
}
//initializing
if (bean instanceof ChenLeiInitializingBean) {
((ChenLeiInitializingBean) bean).afterPropertiesSet();
}
//postprocess 这种就是所有的bean都会经过所有的processor处理
//想要特别的bean处理 只需要在postProcessBeforeInitialization 实现逻辑就行
for (ChenLeiBeanPostProcessor processor : processorList) {
//aop 一般在这里使用 cglib来创建代理对象 所以原来的bean就是代理对象
bean = processor.postProcessAfterInitialization(bean, beanName);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return bean;
}
}
定义一个beandefinition,用来保存bean的信息,是否是单例模式,是否懒加载等
public class ChenLeiBeanDefinition {
private Class aClass;//bean的类型
private String scope;//是否是单例bean
private boolean lazy;//是否懒加载
public Class getaClass() {
return aClass;
}
public void setaClass(Class aClass) {
this.aClass = aClass;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public boolean isLazy() {
return lazy;
}
public void setLazy(boolean lazy) {
this.lazy = lazy;
}
}
定义一个@conponent 标记哪些是我们要加载bean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiComponent {
String value() default "";
}
定义scope 来确定bean是单例还是多例
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiScope {
//两种类型 singleton单例和 prototype 原型(多例)
String value() default"";
}
componentscan
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiComponentscan {
String value() default "";
}
自动注入
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChenLeiAutowired {
}
初始化接口
public interface ChenLeiInitializingBean {
void afterPropertiesSet();
}
processor
public interface ChenLeiBeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) ;
Object postProcessAfterInitialization(Object bean, String beanName) ;
}
git地址