今天我更新了一篇jvm垃圾回收的算法和垃圾回收器的内部逻辑,但是看的人不多啊......貌似大家还是比较喜欢看源码吧,毕竟实战要比理论用的多。

  这篇文章不会详细的深入底层源码,只是基于注解和配置来说说我们的spring的使用,别小看基础,保证有你没用过的注解和配置,走起。
我们先来建立一个maven项目,引入spring文件,不爱弄的在文章最下面有代码地址可以去下载。先看,后面自己下载代码自己去尝试。先给你们吧,边尝试边看吧。码云地址:https://gitee.com/dwyui/springboke.git

一、IOC容器注册组件的方式

1.基础XML注入Bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.springIOC.bean.CarBean"></bean><!--id是唯一表示,class是全路径 -->
</beans>
package com.springIOC;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext cac = new ClassPathXmlApplicationContext("config.xml");
Object car = cac.getBean("car");
}
}

是不是超级简单的,我们由浅入深一点点来。

2.基于注解的方式来配置

package com.springIOC2.config;

import com.springIOC.bean.CarBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class MainConfig {
@Bean
public CarBean car(){//注意方法名
return new CarBean();
}
}
package com.springIOC2;

import com.springIOC2.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext aca = new AnnotationConfigApplicationContext(MainConfig.class);
Object car = aca.getBean("car");
}
}

我们通过方法名就可以直接得到我们的对象了,默认就是按照方法来装配。也可以通过@Bean(value="newName") 来指定装配的名字。

 3.按照包扫描的方式装配(重点),使用@ComponentScan(basePackages={"包的全路径"})

package com.springIOC3.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan(basePackages = {"com.springIOC3"})
public class MainConfig { }
package com.springIOC3;

import com.springIOC3.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest { /**
* 基础@CompentScan,包扫描方式来配置
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext aca = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanDefinitionNames = aca.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
}
}

这里在来说几个参数,excludeFilters排除某一些对象,语法如下

excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),  //排除所有Controller的注解类,多个value可以用逗号分隔
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {RepositoryBean.class}) //排除RepositoryBean类对象

}

FilterType有五种,分别是ANNOTATION(注解类)ASSIGNABLE_TYPE(类名),ASPECTJ(不常用,文档说AspectJ类型模式表达式匹配),REGEX(正则表达式匹配),CUSTOM(自定义),常用的三种我标记了红色。下面看一下具体写法

package com.springIOC3b.config;

import com.springIOC3b.repository.RepositoryBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller; @Configuration
@ComponentScan(basePackages = {"com.springIOC3b"},excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = {RepositoryBean.class})
})
/**
* 1:排除用法 excludeFilters(排除@Controller注解的,和RepositoryBean类)
*/
public class MainConfig { }

刚才我们说到了自定义过滤,我们来看一下怎么写自定义的过滤,实现我们TypeFilter接口,重写我们的match即可,只关注返回的true。下面是一个事例

package com.springIOC3c.config;

import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter; import java.io.IOException; public class CustomFilterType implements TypeFilter { @Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类的注解源信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前类的class的源信息
ClassMetadata classMetadata = metadataReader.getClassMetadata(); //获取当前类的资源信息
Resource resource = metadataReader.getResource(); if (classMetadata.getClassName().contains("RepositoryBean")) { //这里注意,他是一个包含的匹配规则,即使我写成下面注释掉那样也可以的
return true;
}
// if (classMetadata.getClassName().contains("ryBean")) {
// return true;
// }
return false;
}
}

与包含相反的还有一个,只允许引入什么,也就是我们的includeFilters,需要注意需要把useDefaultFilters属性设置为false(true表示扫描全部的)。语法和excludeFilters完全一致

package com.springIOC3d.config;

import com.springIOC3d.service.ServiceBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller; @Configuration
@ComponentScan(basePackages = {"com.springIOC3d"},includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,value = {Controller.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,value = ServiceBean.class)
},useDefaultFilters = false)
/**
* 只许引入*** includeFilters(只许引入@Controller注解和ServiceBean类),useDefaultFilters设置为false,关闭全包扫描
*/
public class MainConfig { }

4.回过头来,我们看一下Bean的作用域。

@Lazy懒加载,使用才实例化,看下代码,我们在Bean里加入构造方法,更方便得出什么时候实例化的。

package com.springIOC4.config;

import com.springIOC4.bean.CarBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; @Configuration
public class MainConfig {
@Bean
@Lazy
public CarBean car(){
return new CarBean();
}
}

指定@Scpoe可以有四种作用域

a) singleton 单实例的(默认),单例的生命周期有spring容器来控制,非懒加载时在spring实例化以后就产生了对象,容器销毁则对象销毁

package com.springIOC4b.config;

import com.springIOC4b.bean.CarBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope; @Configuration
public class MainConfig {
@Bean
@Scope(value = "singleton")
public CarBean car(){
return new CarBean();
}
}
package com.springIOC4b;

import com.springIOC4b.bean.CarBean;
import com.springIOC4b.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest {
/**
* @Scope(value = "singleton")单例,默认也是@Scope(value = "singleton")
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext aca = new AnnotationConfigApplicationContext(MainConfig.class);
CarBean car = (CarBean)aca.getBean("car");
CarBean car2 = (CarBean)aca.getBean("car");
System.out.println(car == car2); // # true
}
}

输出结果为true,说明我们的对象是单例的,单例的对象,生命周期由spring来管理的。

b) prototype 多实例的

package com.springIOC4c.config;

import com.springIOC4c.bean.CarBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope; @Configuration
public class MainConfig {
@Bean
@Scope(value = "prototype")
public CarBean car(){
return new CarBean();
}
}
package com.springIOC4c;

import com.springIOC4c.bean.CarBean;
import com.springIOC4c.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest {
/**
* @Scope(value = "prototype")多例
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext aca = new AnnotationConfigApplicationContext(MainConfig.class);
CarBean car = (CarBean)aca.getBean("car");
CarBean car2 = (CarBean)aca.getBean("car");
System.out.println(car == car2); // # false
}
}

多例的不受ioc容器来管理,销毁时是由GC来清理的,还有request同一次请求和session同一个会话级别的,这里就不一一演示了。

5.@Configuration注解,来判断是否注入Bean的。

package com.springIOC5.config;

import com.springIOC5.bean.CarBean;
import com.springIOC5.bean.UserBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; @Configuration
public class MainConfig { @Bean(value = "user")
public UserBean userBean() {
return new UserBean();
} @Bean
@Conditional(value = IOCConditional.class)
public CarBean carBean() {
return new CarBean();
}
}
package com.springIOC5.config;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata; public class IOCConditional implements Condition { @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getBeanFactory().containsBean("user")) { //这里必须和Bean的名称完全一致。
return true;
}
return false;
}
}

上面的代码什么意思呢?就是我们是否需要注入carBean,如果包含user这个对象,就注入我们的carBean,不包含就不注入,这里有个意思的事,Configuration配置里类的注入是有顺序的,我们必须把我们作为判断条件的Bean放在上面,否则Conditional会识别你没有那个判断条件的Bean。

6.@Import引入方式注入Bean

package com.springIOC6.config;

import com.springIOC6.bean.CarBean;
import com.springIOC6.bean.UserBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; @Configuration
@Import({CarBean.class, UserBean.class})
public class MainConfig { }

直接在注解内写入我们的要注入的类即可,也可以使用接口的方式来实现,我们来看换一下。

package com.springIOC6b.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; @Configuration
@Import({ImportSelector.class})
public class MainConfig { }
package com.springIOC6b.config;

import org.springframework.core.type.AnnotationMetadata;

public class ImportSelector implements org.springframework.context.annotation.ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.springIOC6b.bean.CarBean","com.springIOC6b.bean.UserBean"};
}
}

实现ImportSelector类,然后返回类名全路径即可。自动装配就是基于@Import实现的。

实现ImportBeanDefinitionRegistrar,重写registerBeanDefinitions方法,也是可以的。

package com.springIOC6c.config;

import com.springIOC6c.bean.CarBean;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata; public class ImportSelectorRegister implements ImportBeanDefinitionRegistrar { @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(CarBean.class);
registry.registerBeanDefinition("CarBean",rootBeanDefinition);
}
}

7.通过FactoryBean注入

package com.springIOC7.config;

import com.springIOC7.bean.UserBean;
import org.springframework.beans.factory.FactoryBean; public class IOCFactoryBean implements FactoryBean<UserBean> { @Override
public UserBean getObject() throws Exception {//指定对象
return new UserBean();
} @Override
public Class<?> getObjectType() {//指定类型
return UserBean.class;
} @Override
public boolean isSingleton() {//指定是否为单例
return true;
}
}
package com.springIOC7.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class MainConfig {
@Bean
public IOCFactoryBean iocFactoryBean(){
return new IOCFactoryBean();
}
}
package com.springIOC7;

import com.springIOC7.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest { /**
* FactoryBean注入
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext aca = new AnnotationConfigApplicationContext(MainConfig.class);
Object carBean = aca.getBean("iocFactoryBean");//取出userBean
System.out.println(carBean); Object iocFactoryBean = aca.getBean("&iocFactoryBean");//取得FactoryBean
System.out.println(iocFactoryBean);
}
}

说到这所有往IOC容器中添加组件的方式就全部说完了,简单总结一下:

  @Bean注入,可以指定四种作用域,单例,多例(生命周期不受IOC容器管理),一次请求和一次会话,也可以设置懒加载,

  @ComponentScan指定包扫描的方式来注入,配合@Controller,@Repository,@Service,@Component注解来使用。

  @Import方式注入,两种实现类ImportSelector和ImportBeanDefinitionRegistrar两种方式。

  @FactoryBean,工程Bean的方式也可以注入。注意不带&是取得最终对象,带&是取得真实Bean。三个方法,一个指定对象,一个指定类型,一个指定是否为单例。

二、Bean的生命周期---初始化方法和销毁方法

针对单实例bean的话,容器启动的时候,bean的对象就创建了,而且容器销毁的时候,也会调用Bean的销毁方法。

针对多实例bean的话,容器启动的时候,bean是不会被创建的而是在获取bean的时候被创建,而且bean的销毁不受IOC容器的管理。

1.我们先来看个最简单的方法,用initMethod和destroyMethod来指定我们的初始化方法和销毁方法

package com.springlifeCycle1a.config;

import com.springlifeCycle1a.bean.CarBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class MainConfig { @Bean(initMethod = "init",destroyMethod = "destroy")
public CarBean car() {
return new CarBean();
}
}

我们在指定了我们的init初始方法,销毁方法为destroy方法。调用顺序是,Car的构造方法,Car的init方法,Car的destroy方法,也可以自己尝试使用@Lazy注解。码云代码里有可以自己去尝试。

2.通过 InitializingBean和DisposableBean 的两个接口实现bean的初始化以及销毁方法 

package com.springlifeCycle2a.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; public class CarBean implements InitializingBean, DisposableBean {
public CarBean() {
System.out.println("我是Car");
} public void afterPropertiesSet() {
System.out.println("我是初始化init");
} public void destroy() {
System.out.println("我是销毁destroy");
}
}

3.通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法

package com.springlifeCycle3.bean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; public class CarBean {
public CarBean() {
System.out.println("我是Car");
} @PostConstruct
public void init() {
System.out.println("我是初始化init--PostConstruct");
} @PreDestroy
public void destory() {
System.out.println("我是销毁destroy--PreDestroy");
} }

4.通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程 (这个方法后面讲源码的时候会去讲内部实现,自己觉得有必要看这个的源码

package com.springlifeCycle4.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component; @Component
public class LifeBeanPostProcessor implements BeanPostProcessor { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化方法" + beanName);
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("销毁方法" + beanName);
return bean;
}
}

这里也总结一下,我们来指定容器内对象的初始化方法和销毁方法的方式一共有四种

1.用@Bean的initMethod 和destroyMethod 来给予初始化方法和销毁方法。

2.通过 InitializingBean和DisposableBean 的二个接口实现bean的初始化以及销毁方法。

3.通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法。

4.通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程。

三、给属性赋值

  这里的东西不多,我就尽快说一下啦,赋值的方式有三种我们来看一下。

package com.springValue.config;

import com.springValue.bean.CarBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; @Configuration
@PropertySource(value = "classpath:carBean.properties",encoding = "utf-8") //指定外部文件的位置
public class MainConfig { @Bean
public CarBean carBean() {
return new CarBean();
}
}
import org.springframework.beans.factory.annotation.Value;

public class CarBean {

    @Value("宝马")//通过普通的方式
private String name; @Value("#{5-2}")//spel方式来赋值
private int carNum; @Value("${carBean.realName}")//通过读取外部配置文件的值
private String realName; }//自己记得加get set方法。

这里值得一提的就是导入文件最好设置一下encoding = "utf-8",不然汉字会乱码。

四、自动装配:

  主动装配平时是我们最熟悉的,用的也是最多的,我们来复习一下。

1.@Autowired  自动装配首先时按照类型进行装配,若在IOC容器中发现了多个相同类型的组件,那么就按照 属性名称来进行装配

package com.springxAutowired1.config;

import com.springxAutowired1.dao.AutowiredDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan(value = "com.springxAutowired1.service")
public class MainConfig { @Bean
public AutowiredDao autowiredDao1(){
return new AutowiredDao(1);
} @Bean
public AutowiredDao autowiredDao2(){
return new AutowiredDao(2);
}
}
package com.springxAutowired1.service;

import com.springxAutowired1.dao.AutowiredDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; @Service
public class ServiceBean { @Autowired
private AutowiredDao autowiredDao2; public ServiceBean() {
System.out.println("我是serviceBean");
} @Override
public String toString() {
return "ServiceBean{" +
"AutowiredDao=" + autowiredDao2 +
'}';
}
}

在这里我们设置了两个AutowiredDao的对象,一个标识为1,一个标识为2,ServiceBean默认是按照名字来装配的。

2.我们也可以通过@Qualifier来指定装配名字。

package com.springxAutowired1b.service;

import com.springxAutowired1b.dao.AutowiredDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; @Service
public class ServiceBean { @Autowired
@Qualifier(value = "autowiredDao1")
private AutowiredDao autowiredDao2; public ServiceBean() {
System.out.println("我是serviceBean");
} @Override
public String toString() {
return "ServiceBean{" +
"AutowiredDao=" + autowiredDao2 +
'}';
}
}

3.我们使用Qualifier是如果名字写错了,可能装配错误会报错,这时我们可以使用required = false来阻止异常的抛出

package com.springxAutowired3.service;

import com.springxAutowired3.dao.AutowiredDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; @Service
public class ServiceBean { @Qualifier(value = "autowiredDaoError")
@Autowired(required = false)
private AutowiredDao autowiredDao2; public ServiceBean() {
System.out.println("我是serviceBean");
} @Override
public String toString() {
return "ServiceBean{" +
"AutowiredDao=" + autowiredDao2 +
'}';
}
}

注意:这里我并没有说@Resource注解,这个注解其实不是spring里的,是JSR250规范的,但是不支持@Primary 和@Qualifier的支持

五、环境切换:

我们有时候需要通过不同的环境来切换我们的配置,我们通过@Profile注解,来根据环境来激活标识不同的Bean,

@Profile标识在类上,那么只有当前环境匹配,整个配置类才会生效

@Profile标识在Bean上 ,那么只有当前环境的Bean才会被激活

package com.springxAutowired4.config;

import com.springxAutowired4.bean.Environment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile; @Configuration
public class MainConfig { @Bean
@Profile(value = "test")
public Environment environment_test() {
return new Environment("test");
} @Bean
@Profile(value = "dev")
public Environment environment_dev() {
return new Environment("dev");
} @Bean
@Profile(value = "pro")
public Environment environment_pro() {
return new Environment("pro");
}
}

激活切换环境的方法

方法一:通过运行时jvm参数来切换 -Dspring.profiles.active=test,dev,prod多个参数表中间使用英文的逗号来分隔

方法二:通过代码的方式来激活

package com.springxAutowired4;

import com.springxAutowired4.config.MainConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainTest { /**
* 环境切换
* @param args
*/
public static void main(String[] args) {
AnnotationConfigApplicationContext aca = new AnnotationConfigApplicationContext();
aca.getEnvironment().setActiveProfiles("test","dev");//方便演示,我写了两个,一般都是一个的. aca.register(MainConfig.class);
aca.refresh();
for (String beanDefinitionName : aca.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
}

如果两个都写了,按照代码中的来实现,参数不再起作用

今天就说到这里, 大概就这么多吧。后期我也会基于这篇博客来详细的扒一下源码,中间会穿插一些spring的常见面试题。

代码地址:https://gitee.com/dwyui/springboke.git

最进弄了一个公众号,小菜技术,欢迎大家的加入

java架构之路-(spring源码篇)由浅入深-spring实战详细使用的更多相关文章

  1. java架构之路-(源码)mybatis基本使用

    我们今天先来简单了解一下我们持久层框架,mybatis的使用.而且现在的注解成为趋势,我主要说一下注解方向的使用吧(配置文件也会说) 从使用角度只要是三个部分,mybatis-config.xml,m ...

  2. java架构之路-(源码)mybatis的一二级缓存问题

    上次博客我们说了mybatis的基本使用,我们还捎带提到一下Mapper.xml中的select标签的useCache属性,这个就是设置是否存入二级缓存的. 回到我们正题,经常使用mybatis的小伙 ...

  3. java架构之路-(源码)mybatis执行流程源码解析

    这次我们来说说Mybatis的源码,这里只说执行的流程,内部细节太多了,这里只能授之以渔了.还是最近的那段代码,我们来回顾一下. package mybatis; import mybatis.bea ...

  4. Spring源码-IOC部分-Spring是如何解决Bean循环依赖的【6】

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...

  5. Spring源码-AOP部分-Spring是如何对bean实现AOP代理的

    实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 历史文章 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] S ...

  6. java架构之路-(spring源码篇)springIOC容器源码解析(上)

    我们这次来叭叭一下Spring的源码,这次博客主要来说说Spring源码,先粗略的撸一遍,下篇博客选几个重点去说,由于过于复杂,我也是看了一点点,我们先来过一遍源码,然后上流程图,最后我们再回头总结一 ...

  7. spring源码深度解析—Spring的整体架构和环境搭建

    概述 Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用.Spring是于2003 年兴起的一个轻量级的Java 开发框 ...

  8. 框架源码系列六:Spring源码学习之Spring IOC源码学习

    Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的  1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...

  9. spring源码学习(三)--spring循环引用源码学习

    在spring中,是支持单实例bean的循环引用(循环依赖)的,循环依赖,简单而言,就是A类中注入了B类,B类中注入了A类,首先贴出我的代码示例 @Component public class Add ...

随机推荐

  1. set集合的常用方法

    set集合是一种无序不重复的集合   add  (self, *args, **kwargs)                                                      ...

  2. jQuery Validate 可选项

  3. Unity 自定义Inspector面板时的数据持久化问题

    自定义Inspector面板的步骤: Unity内创建自定义的Inspector需要在Asset的任意文件夹下创建一个名字是Editor的文件夹,随后这个文件夹内的cs文件就会被放在vstu生成的Ed ...

  4. 内容协商在视图View上的应用【享学Spring MVC】

    每篇一句 人生很有意思:首先就得活得长.活得长才能够见自己,再长就可以见众生 前言 在经过 前两篇 文章了解了Spring MVC的内容协商机制之后,相信你已经能够熟练的运用Spring MVC提供的 ...

  5. 亲,麻烦给个五星好评!—RatingBar

    引言 上一篇的CheckBox已经让大家越来越接近实战演练了,本章我们继续分享干货给大家,今天介绍一个实用的UI控件RatingBar(星级评分条),对于使用过电商APP(某东,某宝等)的小伙伴们来说 ...

  6. H5 API drawImage的参数

    drawImage(this,120,0,180,150,0,0,180,150); //mg图片上的x坐标 img图片上的y坐标 剪切的宽 剪切的高 在canvas上的x坐标 在canvas上的y坐 ...

  7. 深入浅出TypeScript(2)- 用TypeScript创建web项目

    前言 在第一篇中,我们简单介绍了TypeScript的一些简单语法,那么如果我们只是简单使用TypeScript开发一个web项目,应该做哪些准备?接下来我们就结合TypeScript和Webpack ...

  8. HDU 2147

    题意略. 思路: 题中提到的3种操作,一个是将长方形的n减少1,一个是将m减少1,一个是将n和m同时减少1,都是将长方形规模减少的的操作. 现在我们可以知道,(1,1)先手必输:(1,2),(2,1) ...

  9. [C#] 改进SqliteHelper, 减少拼接SQL语句

    说明:开始几个是基本的方法,后面稍微封装了下 public class SqliteHelper { //连接字符串 private static readonly string str = Conf ...

  10. API 资源隔离系统设计与实现

    (马蜂窝技术原创内容,公众号 ID:mfwtech) Part 1 背景 大交通业务需要对接机票.火车票.租车.接送机等业务的外部供应链,供应商的数据接口大部分通过 HTTP.HTTPS 等协议进行通 ...