spring源代码解析(三):spring
(3)spring源码解析-refresh()方法之前
![(3)spring源码解析-refresh()方法之前](https://img.taocdn.com/s3/m/bd1b8365a88271fe910ef12d2af90242a895ab4e.png)
(3)spring源码解析-refresh()⽅法之前本⽂是作者原创,版权归作者所有.若要转载,请注明出处.本⽂源码版本5.1.x.话不多说,开始⾸先是配置类@Configuration@ComponentScan("com.day01")public class SpringConfig {}IndexService@Servicepublic class IndexService {public IndexService(){System.out.println("IndexService 构造⽅法");}@PostConstructpublic void init(){System.out.println("IndexService init⽅法");}public void hello(){System.out.println("IndexService hello");}}测试类public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(SpringConfig.class);//AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(IndexService.class);IndexService indexService = (IndexService) applicationContext.getBean("indexService");indexService.hello();System.out.println(indexService);}第⼀⾏点进去public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {//annotatedClasses ---> 配置类的class对象this();register(annotatedClasses);refresh();}今天我们先看refresh()⽅法之前的源码this()调的构造器如下public AnnotationConfigApplicationContext() {/*** ⽗类的构造⽅法* 创建⼀个读取注解的Bean定义读取器* 什么是BeanDefinition*/super();this.reader = new AnnotatedBeanDefinitionReader(this);//可以⽤来扫描包或者类,继⽽转换成BeanDefinition//但是实际上我们扫描包⼯作不是scanner这个对象来完成的//是spring⾃⼰new的⼀个ClassPathBeanDefinitionScanner//这⾥的scanner仅仅是为了程序员能够在外部调⽤AnnotationConfigApplicationContext对象的scan⽅法this.scanner = new ClassPathBeanDefinitionScanner(this);}/*** 这个类顾名思义是⼀个reader,⼀个读取器* 读取什么呢?还是顾名思义:AnnotatedBeanDefinition意思是读取⼀个被加了注解的BeanDefinition* 这个类在构造⽅法中实例化的*/private final AnnotatedBeanDefinitionReader reader;/*** 同意顾名思义,这是⼀个扫描器,扫描所有加了注解的bean* 同样是在构造⽅法中被实例化的*/private final ClassPathBeanDefinitionScanner scanner;先看super()⽗类构造器public GenericApplicationContext() {this.beanFactory = new DefaultListableBeanFactory();}可以看出初始化beanFactory 为默认实现DefaultListableBeanFactory我们看⼀下些DefaultListableBeanFactory的属性和⽅法public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {/** Map of bean definition objects, keyed by bean name. */private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);/** List of bean definition names, in registration order. */private volatile List<String> beanDefinitionNames = new ArrayList<>(256);//⼿动注册的单例对象的名称列表,按注册顺序排列/** List of names of manually registered singletons, in registration order. */private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);@Overridepublic <T> T getBean(Class<T> requiredType) throws BeansException {return getBean(requiredType, (Object[]) null);}@SuppressWarnings("unchecked")@Overridepublic <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {Assert.notNull(requiredType, "Required type must not be null");Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);if (resolved == null) {throw new NoSuchBeanDefinitionException(requiredType);}return (T) resolved;}}可以看出,这是bean⼯⼚的实现类,⾥⾯有存BeanDefinition和beanDefinitionNames 的map和getBean等⽅法⽗类构造器结束,就是实例了⼀个默认的bean⼯⼚,继续下⼀⾏this.reader = new AnnotatedBeanDefinitionReader(this);点进去看源码public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {this(registry, getOrCreateEnvironment(registry));}这⾥BeanDefinitionRegistry是⼀个BeanDefinition注册器public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");Assert.notNull(environment, "Environment must not be null");this.registry = registry;this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);}继续看最后⼀⾏public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {registerAnnotationConfigProcessors(registry, null);}继续跟进去public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);//AnnotationAwareOrderComparator主要能解析@Order注解和@Priority}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());//ContextAnnotationAutowireCandidateResolver提供处理延迟加载的功能}}//a Set of BeanDefinitionHolders, containing all bean definitions//BeanDefinitionHolder是存储BeanDefinitionName和BeanDefinition的⼀个数据结构Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);//BeanDefinitio的注册,这⾥很重要,需要理解注册每个bean的类型,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME=internalConfigurationAnnotationProcessorif (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {//ConfigurationClassPostProcessor是⼀个BeanFactory的后置处理器,主要功能是解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解 //需要注意的是ConfigurationClassPostProcessor的类型是BeanDefinitionRegistryPostProcessor//⽽ BeanDefinitionRegistryPostProcessor 最终实现BeanFactoryPostProcessor这个接⼝RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}//AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME=internalAutowiredAnnotationProcessorif (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {//AutowiredAnnotationBeanPostProcessor是解析AutoWired注解的BeanPostProcessor//AutowiredAnnotationBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor//MergedBeanDefinitionPostProcessor 最终实现了 BeanPostProcessorRootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}//COMMON_ANNOTATION_PROCESSOR_BEAN_NAME=internalCommonAnnotationProcessor// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {//CommonAnnotationBeanPostProcessor⽀持对@PostConstruct和@PreDestroy注解,以及对@Resource注解的处理RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}//PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME=internalPersistenceAnnotationProcessor,跳过,不重要// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); }def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); }//EVENT_LISTENER_PROCESSOR_BEAN_NAME=internalEventListenerProcessorif (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {//EventListenerMethodProcessor⽀持事件监听,不太熟RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}//EVENT_LISTENER_FACTORY_BEAN_NAME=internalEventListenerFactoryif (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {//DefaultEventListenerFactory不太了解,事件监听相关RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;}这⾥的BeanDefinitionHolder看下public class BeanDefinitionHolder implements BeanMetadataElement {private final BeanDefinition beanDefinition;private final String beanName;@Nullableprivate final String[] aliases; //省略}可以认为:BeanDefinitionHolder是存储BeanDefinitionName和BeanDefinition的⼀个数据结构debug看下最后⼀⾏的结果可以看出,bean⼯⼚已经存在5个BeanDefinition,我们继续看下⾯的源码读取器看完了,扫描器先不看了,我们看register(annotatedClasses);⽅法public void register(Class<?>... annotatedClasses) {Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");this.reader.register(annotatedClasses);//被注解的类}继续跟下去public void register(Class<?>... annotatedClasses) {for (Class<?> annotatedClass : annotatedClasses) {registerBean(annotatedClass);}}这⾥循环处理所有要处理的annotated类。
spring事务管理器的源码和理解
![spring事务管理器的源码和理解](https://img.taocdn.com/s3/m/cba7cdcd360cba1aa811daea.png)
以前说了大多的原理,今天来说下spring的事务管理器的实现过程,顺带源码干货带上。
其实这个文章唯一的就是带着看看代码,但是前提你要懂得动态代理以及字节码增强方面的知识(/xieyuooo/article/details/7624146),关于annotation在文章:/xieyuooo/article/details/8002321也有说明,所以本文也就带着看看代码而已。
关于annotation这里就不说了,我们看看平时一般会怎么样来配置spring的配置,通过配置文件反射源码如何看看。
一般来讲首先会配置一个datasource,至于你配置什么连接池还是用JNDI这里就不提到细节,总之我们认为配置的spring的全局名称为dataSource就可以了。
接下来会将datasource交给各种连接池的操作类,如:ibatis、jdbcTemplate等等,这些不是我们关心的重点,我们需要关心的是dataSource是谁来管理了,在spring中配置了给一个DataSourceTransactionManager的对象:<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource"><ref bean="dataSource" /></property></bean>ok,先记录下来,至于下面的NameMatchTransactionAttributeSource描述了那些情况要进行事务管理,我们将它理解为一种属性配置,在运行时需要解析即可,所以他也并不是我们特别需要的重点。
SpringIOC源码分析
![SpringIOC源码分析](https://img.taocdn.com/s3/m/84de7299d1d233d4b14e852458fb770bf78a3b0d.png)
SpringIOC源码分析Spring 最重要的概念是 IOC 和 AOP,本篇⽂章其实就是要带领⼤家来分析下 Spring 的 IOC 容器。
既然⼤家平时都要⽤到 Spring,怎么可以不好好了解 Spring 呢?阅读本⽂并不能让你成为 Spring 专家,不过⼀定有助于⼤家理解 Spring 的很多概念,帮助⼤家排查应⽤中和Spring 相关的⼀些问题。
阅读建议:读者⾄少需要知道怎么配置 Spring,了解 Spring 中的各种概念,少部分内容我还假设读者使⽤过 SpringMVC。
本⽂要说的 IOC 总体来说有两处地⽅最重要,⼀个是创建 Bean 容器,⼀个是初始化 Bean,如果读者觉得⼀次性看完本⽂压⼒有点⼤,那么可以按这个思路分两次消化。
读者不⼀定对 Spring 容器的源码感兴趣,也许附录部分介绍的知识对读者有些许作⽤。
我采⽤的源码版本是 4.3.11.RELEASE,算是 5.0.x 前⽐较新的版本了。
为了降低难度,本⽂所说的所有的内容都是基于 xml 的配置的⽅式,实际使⽤已经很少⼈这么做了,⾄少不是纯 xml 配置,不过从理解源码的⾓度来看⽤这种⽅式来说⽆疑是最合适的。
如果读者对注解⽅式的源码感兴趣,也许等我有时间的时候可以写篇⽂章介绍介绍。
我希望能将此⽂写成⼀篇 Spring IOC 源码分析的好⽂章,希望通过本⽂可以让读者不惧怕阅读 Spring 源码。
为了保持⽂章的严谨性,如果读者发现我哪⾥说错了请⼀定不吝指出,⾮常希望可以听到读者的声⾳。
引⾔先看下最基本的启动 Spring 容器的例⼦:1 2 3public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationfile.xml"); }以上代码就可以利⽤配置⽂件来启动⼀个 Spring 容器了,请使⽤ maven 的⼩伙伴直接在 dependencies 中加上以下依赖即可,我⽐较反对那些不知道要添加什么依赖,然后把 Spring 的所有相关的东西都加进来的⽅式。
Spring源码分析-事件机制
![Spring源码分析-事件机制](https://img.taocdn.com/s3/m/f77ab511bfd5b9f3f90f76c66137ee06eff94e20.png)
Spring源码分析-事件机制为了⽅便快速理解,我还是先不讲原理,直接⽰例开篇吧。
⼀、⽰例1.定义⼀个Listener 实现了ApplicationListener 接⼝@Componentpublic class MyTestListener implements ApplicationListener{@Overridepublic void onApplicationEvent(ApplicationEvent event) {System.out.println("向zookeeper注册暴露的服务...");}}2.applicationContext.xml 添加如下内容<context:annotation-config /><context:component-scan base-package="com.event"/>3.测试public class SpringEventTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");}}控制台输出:在这⾥不知道⼤家有没有发现,我这个main⽅法除了new ClassPathXmlApplicationContext("classpath:applicationContext.xml");其它什么也没做,那么为何MyTestListener 中的 onApplicationEvent ⽅法就执⾏了?⼆、源码分析1.先在⾃定义的listener类的 onApplicationEvent ⽅法进⾏断点调试(这⾥主要是为了通过Debug模式的线程栈查看从执⾏main⽅法开始到最后执⾏onApplicationEvent ⽅法结束都调⽤了哪些⽅法)2.Debug 运⾏测试类3.通过 Debug 线程栈分析源码执⾏过程(这⾥展⽰从main⽅法开始到onApplicationEvent⽅法的调⽤过程)从这个线程栈中可以看出,执⾏到refresh ⽅法中的finishRefresh 时,即执⾏publishEvent,关于refresh ⽅法我在这⾥不做过多的说明。
springaop源码分析(三)@Scope注解创建代理对象
![springaop源码分析(三)@Scope注解创建代理对象](https://img.taocdn.com/s3/m/e705e73ce3bd960590c69ec3d5bbfd0a7956d5aa.png)
springaop源码分析(三)@Scope注解创建代理对象⼀.源码环境的搭建:@Component@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedProxyMode.TARGET_CLASS)public class MyMath implements Calc{public Integer add(int num1,int num2){return num1+num2;}}@Configuration@ComponentScan("com.yang.xiao.hui.aop")public class App{public static void main( String[] args ){ApplicationContext ctx = new AnnotationConfigApplicationContext(App.class);MyMath myMath = (MyMath)ctx.getBean("myMath");System.out.println(myMath.getClass());System.out.println(ctx.getBean("scopedTarget.myMath").getClass());}}启动main⽅法:⼆.源码分析,先看Scope注解:scope注解的proxyMode的属性决定了被该注解标注的类是否会被代理,这是⼀个枚举,有如下⼏个值:本次测试代码使⽤的是cglib代理,被Scope标注的对象,如果代理模式是jdk或者cglib代理的话,会在spring容器中产⽣2个bean,⼀个是代理的bean,⼀个是原始的bean,原始的bean的beanName被命名为:scopedTarget.xx:debug调试:省略n步:我们在这个⽅法⾥⾯可以看到spring是如何解析主启动类,扫描到其他的bean的:protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)throws IOException {if (configClass.getMetadata().isAnnotated(Component.class.getName())) { //解析Component注解// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass);}// Process any @PropertySource annotationsfor (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if (this.environment instanceof ConfigurableEnvironment) {processPropertySource(propertySource);}else {("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +"]. Reason: Environment must implement ConfigurableEnvironment");}}// Process any @ComponentScan annotationsSet<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( //解析Component注解ComponentScan.classsourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);if (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// The config class is annotated with @ComponentScan -> perform the scan immediatelySet<BeanDefinitionHolder> scannedBeanDefinitions =ponentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); //componentScan解析器,对该注解进⾏解析// Check the set of scanned definitions for any further config classes and parse recursively if neededfor (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if (bdCand == null) {bdCand = holder.getBeanDefinition();}if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {parse(bdCand.getBeanClassName(), holder.getBeanName());}}}}//..............................省略部分代码}protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {Set<BeanDefinition> candidates = findCandidateComponents(basePackage);//通过包名,扫描该包名下的所有bean的定义信息for (BeanDefinition candidate : candidates) {ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); //scope注解解析器,获取Scope注解的属性信息,封装成ScopeMetadatacandidate.setScope(scopeMetadata.getScopeName());String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);//beanName⽣成器,这⾥是myMathif (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}if (checkCandidate(beanName, candidate)) {BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);definitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //这⾥处理scope注解,下⾯跟进这个beanDefinitions.add(definitionHolder);registerBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,BeanDefinitionRegistry registry, boolean proxyTargetClass) {String originalBeanName = definition.getBeanName();//原始的beanName: myMathBeanDefinition targetDefinition = definition.getBeanDefinition(); //原始的bean定义信息String targetBeanName = getTargetBeanName(originalBeanName); //scopedTarget.myMath// Create a scoped proxy definition for the original bean name,// "hiding" the target bean in an internal target definition.RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class); //创建⼀个代理对象proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName)); //将原始的bean定义信息作为被装饰的bean定义信息proxyDefinition.setOriginatingBeanDefinition(targetDefinition);//设置原始的bean定义信息proxyDefinition.setSource(definition.getSource());proxyDefinition.setRole(targetDefinition.getRole());proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);if (proxyTargetClass) {targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.}else {proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);}// Copy autowire settings from original bean definition.proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());proxyDefinition.setPrimary(targetDefinition.isPrimary());if (targetDefinition instanceof AbstractBeanDefinition) {proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);}// The target bean should be ignored in favor of the scoped proxy.targetDefinition.setAutowireCandidate(false);targetDefinition.setPrimary(false);// Register the target bean as separate bean in the factory.registry.registerBeanDefinition(targetBeanName, targetDefinition);//这⾥将原始的bean定义信息注册到了spring容器,⽽bean的名称是scopedTarget.myMath// Return the scoped proxy definition as primary bean definition// (potentially an inner bean).return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases()); //这⾥将代理bean定义信息返回,bean的名称是原始的beanName,myMath,该beanHodler返回去后,会被注册到spring }总结:⼀个被Scope注解标注的类,如果scope的proxyMode不是no 或者defualt,那么会在spring创建2个bean,⼀个是代理bean,类型为ScopedProxyFactoryBean.class,⼀个是原始的bean:这⾥我们的MyMath类,⽣成了2个beanDefinition,⼀个是代理的beanDefinition,beanName为myMath,⼀个是原始的beanDefinition,beanName为scopedTarget.myMath;下⾯我们要分析ScopedProxyFactoryBean的创建过程了,我们知道XXFactoryBean会有⼀个getObject()⽅法返回XX代理对象:先看ScopedProxyFactoryBean继承体系通过继承图,我们知道,ScopedProxyFactoryBean实现了BeanFactoryAware接⼝,因此在ScopedProxyFactoryBean的创建过程中,会回调setBeanFactory(BeanFactory beanFactory),所以我们debug在该⽅法:我们详细看看该⽅法:@Overridepublic void setBeanFactory(BeanFactory beanFactory) {if (!(beanFactory instanceof ConfigurableBeanFactory)) {throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);}ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;this.scopedTargetSource.setBeanFactory(beanFactory);ProxyFactory pf = new ProxyFactory(); //创建代理⼯⼚pf.copyFrom(this);pf.setTargetSource(this.scopedTargetSource);Assert.notNull(this.targetBeanName, "Property 'targetBeanName' is required");Class<?> beanType = beanFactory.getType(this.targetBeanName);//获取被代理类if (beanType == null) {throw new IllegalStateException("Cannot create scoped proxy for bean '" + this.targetBeanName +"': Target type could not be determined at the time of proxy creation.");}if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader())); //获取被代理类的所有实现的接⼝}// Add an introduction that implements only the methods on ScopedObject.ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject));//这⾥添加了⼀个增强器,在执⾏⽬标⽅法时,会拦截// Add the AopInfrastructureBean marker to indicate that the scoped proxy// itself is not subject to auto-proxying! Only its target bean is.pf.addInterface(AopInfrastructureBean.class);this.proxy = pf.getProxy(cbf.getBeanClassLoader());//创建代理对象}创建代理对象过程,跟之前aop源码分析⼀和源码分析⼆的时侯分析的⼀样了,这⾥不重复了。
Spring源码分析基本介绍
![Spring源码分析基本介绍](https://img.taocdn.com/s3/m/e1773ed659f5f61fb7360b4c2e3f5727a5e924fe.png)
Spring源码分析基本介绍摘要:本⽂结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。
若有描述错误之处,欢迎指正。
前⾔作为⼀名开发⼈员,阅读源码是⼀个很好的学习⽅式。
本⽂将结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码,若有描述错误之处,欢迎指正。
Spring是2003年兴起的⼀个轻量级Java开源框架,旨在解决企业应⽤开发的复杂性。
Spring发展⾄今,衍⽣出⾮常丰富的模块,并应⽤在多种场景,⽐如:桌⾯应⽤,Web应⽤等。
Spring的模块化可以允许你只使⽤需要的模块,⽽不必全部引⼊。
⽬录⼀、整体架构1. 核⼼容器2. 数据访问/集成3. Web4. AOP5. Test⼆、设计理念三、使⽤场景1. 典型的Spring web应⽤程序2. Spring中间层使⽤第三⽅web框架3. 远程调⽤4. EJBs-包装现存POJOs⼀、整体架构Spring框架是⼀个分层架构,他包含⼀系列的功能要素,并被分为⼤约20个模块,如下图所⽰(很遗憾,并没有找到Spring5的架构图,下图是Spring4的,但结合Spring5的源码来看,该图还是能够体现Spring5的核⼼模块)这些模块被总结为以下⼏部分。
1. 核⼼容器Core Container(核⼼容器)包含有Core、Beans、Context和Expression Language模块。
Core和Beans模块是框架的基础部分,提供IoC(控制反转)和DI(依赖注⼊)特性。
这⾥的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
Core模块主要包含Spring框架基本的核⼼⼯具类,Spring的其他组件都要使⽤到这个包⾥的类,Core模块是其他组件的基本核⼼。
当然你也可以在⾃⼰的应⽤系统中使⽤这些⼯具类。
Spring系列(三):SpringIoC源码解析
![Spring系列(三):SpringIoC源码解析](https://img.taocdn.com/s3/m/7f51305cf11dc281e53a580216fc700abb6852c4.png)
Spring系列(三):SpringIoC源码解析⼀、Spring容器类继承图⼆、容器前期准备 IoC源码解析⼊⼝:/*** @desc: ioc原理解析启动* @author: toby* @date: 2019/7/22 22:20*/public class PrincipleMain {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrincipleConfig.class);}} 调⽤构造函数AnnotationConfigApplicationContext 调⽤this(),会默认先调⽤⽗类的⽆参构造函数,为ApplicationContext上下⽂对象初始beanFactory = new DefaultListableBeanFactory() 在调⽤当前类的this(),也就是调⽤⾃⼰的⽆参构造函数: 进到创建注解模式下的Bean定义读取器: org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, ng.Object) 主要是注册Spring⾃⾝的⼀些后置处理器public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source) {DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);if (beanFactory != null) {if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);}if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());}}Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);/*** 为我们容器中注册解析主配置类的后置处理器ConfigurationClassPostProcessor* beanName = org.springframework.context.annotation.internalConfigurationAnnotationProcessor*/if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 为我们容器中注册处理@Autowired注解的Bean的后置处理器AutowiredAnnotationBeanPostProcessor* beanName = org.springframework.context.annotation.internalAutowiredAnnotationProcessor*/if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 为我们容器中注册处理@Required属性注解的Bean后置处理器RequiredAnnotationBeanPostProcessor* beanName = org.springframework.context.annotation.internalRequiredAnnotationProcessor*/if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 为我们容器注册处理JSR规范注解的Bean后置处理器CommonAnnotationBeanPostProcessor* beanName = org.springframework.context.annotation.internalCommonAnnotationProcessor*/if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 为我们容器注册处理jpa的Bean的后置处理器org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor*/if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition();try {def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils.class.getClassLoader()));}catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));}/*** 处理监听⽅法的注解解析器EventListenerMethodProcessor*/if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}/*** 注册事件监听器⼯⼚*/if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}return beanDefs;} 读取器初始化完成后,Spring的容器的Bean的定义信息就有Spring⾃⾝的⼀些后置处理器了,Debug如下: 读取器初始化完成后,接下来初始化ClassPath下的Bean定义扫描器:org.springframework.context.annotation.ClassPathBeanDefinitionScanner#ClassPathBeanDefinitionScanner(org.springframework.beans.factory.support.BeanDefinitionRegistry, boolean, org.springframework.core.env.Environment, org.springframework.core.io.ResourceLoader) 类路径下的Bean定义扫描 org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#registerDefaultFilters 注⼊默认的Filterprotected void registerDefaultFilters() {this.includeFilters.add(new AnnotationTypeFilter(Component.class));ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.}try {this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("d", cl)), false));logger.debug("JSR-330 'd' annotation found and supported for component scanning");}catch (ClassNotFoundException ex) {// JSR-330 API not available - simply skip.}} 这⾥需要注意的是为什么new AnnotationTypeFilter(Component.class)就可以处理@Repository,@Service,@Controller这3个注解,原因如下: ⾃此前期准备⼯作完成三、org.springframework.context.support.AbstractApplicationContext#refresh 12⼤步public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//1:准备刷新上下⽂环境prepareRefresh();//2:获取初始化Bean⼯⼚ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//3:对bean⼯⼚进⾏填充属性prepareBeanFactory(beanFactory);try {//4:Spring开放接⼝留给⼦类去实现该接⼝postProcessBeanFactory(beanFactory);//5:调⽤我们的bean⼯⼚的后置处理器invokeBeanFactoryPostProcessors(beanFactory);//6:注册我们bean后置处理器registerBeanPostProcessors(beanFactory);//7:初始化国际化资源处理器initMessageSource();//8:初始化事件多播器initApplicationEventMulticaster();//9:这个⽅法同样也是留个⼦类实现,其中springboot也是从这个⽅法进⾏tomcat的启动onRefresh();//10:把我们的事件监听器注册到多播器上registerListeners();//11:实例化所有的⾮懒加载的单实例beanfinishBeanFactoryInitialization(beanFactory);//12:最后刷新容器发布刷新事件(Spring cloud eureka也是从这⾥启动的)finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}} 第⼀步:prepareRefresh() 准备刷新上下⽂环境:protected void prepareRefresh() {// Switch to active.this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);if (logger.isInfoEnabled()) {("Refreshing " + this);}/*** 初始化上下⽂环境*/initPropertySources();/*** ⽤来校验我们容器启动必须依赖的环境变量的值*/getEnvironment().validateRequiredProperties();/*** 创建⼀个早期事件监听器对象*/if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);}else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}/*** 创建⼀个容器⽤于保存早期待发布的事件集合什么是早期事件了?* 就是我们的事件监听器还没有注册到事件多播器上的时候都称为早期事件*/this.earlyApplicationEvents = new LinkedHashSet<>();} 第⼆步:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 获取初始化的Bean的⼯⼚:protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {//刷新bean⼯⼚()refreshBeanFactory();//返回之前容器准备⼯作的时候创建的的bean⼯⼚也就是DefaultListableBeanFactory(很重要)ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (logger.isDebugEnabled()) {logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);}return beanFactory;} org.springframework.context.support.GenericApplicationContext#refreshBeanFactory,注意只能刷⼀次protected final void refreshBeanFactory() throws IllegalStateException {//由于BeanFactory只能刷新⼀次,多线程情况下可能导致线程安全问题,所有使⽤cas原⼦操作来保证if (!pareAndSet(false, true)) {throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");}//指定Bean⼯⼚的序列化Idthis.beanFactory.setSerializationId(getId());} 第三步:prepareBeanFactory(beanFactory) 对bean⼯⼚进⾏填充属性:protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {//设置bean⼯⼚的类加载器为当前application应⽤上下⽂的加载器beanFactory.setBeanClassLoader(getClassLoader());//为bean⼯⼚设置SPEL表达式解析器对象StandardBeanExpressionResolverbeanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//为我们的bean⼯⼚设置了⼀个propertyEditor属性资源编辑器对象(⽤于后⾯的给bean对象赋值使⽤)beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//注册ApplicationContextAwareProcessor后置处理器⽤来处理ApplicationContextAware接⼝的回调⽅法beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));/*** 当Spring将ApplicationContextAwareProcessor注册后,那么在invokeAwarelnterfaces⽅法中调⽤的Aware类已经不是普通的bean了,* 如ResourceLoaderAware、ApplicationEventPublisherAware、ApplicationContextAware等,那么当然需要在Spring做bean的依赖注⼊的时候忽略它们。
Spring MVC源码分析
![Spring MVC源码分析](https://img.taocdn.com/s3/m/edf510db71fe910ef12df8f2.png)
Request MappingHandlerA 基于@request Mapping对
dapt er
应方法处理
HandlerAdapt er 接口方法
HandlerAdapt er 接口结构图
ViewResolver 与View 详解 找到应的Adapt er 之后就会基于适配器调用业务处理,处理完之后业务方会返回一个 ModelAndView ,在去查找对应的视图进行处理。其在 org.springf ramework.web.servlet .Dispat cherServlet #resolveViewName() 中遍历 viewResolvers 列表查找,如果找不到就会报一个 Could not resolve view wit h name 异常。
5
mv.addObject("name","fox");
6
7
return mv;
8
}
9}
10
2.注解配置
1 <context:component-scan base-package=".controller" /> 2 <!-- 注解驱动 -->
3 <mvc:annotation-driven/>
4
xmlns:context="/schema/context"
5
xmlns:mvc="/schema/mvc"
6
xsi:schemaLocation="/schema/beans
1 // 注解方法
2 @RequestMapping("/hello.do")
Spring源码剖析9:Spring事务源码剖析
![Spring源码剖析9:Spring事务源码剖析](https://img.taocdn.com/s3/m/319fad1bba68a98271fe910ef12d2af90242a824.png)
Spring源码剖析9:Spring事务源码剖析本系列⽂章将整理到我在GitHub上的《Java⾯试指南》仓库,更多精彩内容请到我的仓库⾥查看喜欢的话⿇烦点下Star哈⽂章将同步到我的个⼈博客:本⽂是微信公众号【Java技术江湖】的《Spring和SpringMVC源码分析》其中⼀篇,本⽂部分内容来源于⽹络,为了把本⽂主题讲得清晰透彻,也整合了很多我认为不错的技术博客内容,引⽤其中了⼀些⽐较好的博客⽂章,如有侵权,请联系作者。
该系列博⽂会告诉你如何从spring基础⼊⼿,⼀步步地学习spring基础和springmvc的框架知识,并上⼿进⾏项⽬实战,spring框架是每⼀个Java⼯程师必须要学习和理解的知识点,进⼀步来说,你还需要掌握spring甚⾄是springmvc的源码以及实现原理,才能更完整地了解整个spring技术体系,形成⾃⼰的知识框架。
后续还会有springboot和springcloud的技术专题,陆续为⼤家带来,敬请期待。
为了更好地总结和检验你的学习成果,本系列⽂章也会提供部分知识点对应的⾯试题以及参考答案。
如果对本系列⽂章有什么建议,或者是有什么疑问的话,也可以关注公众号【Java技术江湖】联系作者,欢迎你参与本系列博⽂的创作和修订。
声明式事务使⽤Spring事务是我们⽇常⼯作中经常使⽤的⼀项技术,Spring提供了编程、注解、aop切⾯三种⽅式供我们使⽤Spring事务,其中编程式事务因为对代码⼊侵较⼤所以不被推荐使⽤,注解和aop切⾯的⽅式可以基于需求⾃⾏选择,我们以注解的⽅式为例来分析Spring事务的原理和源码实现。
⾸先我们简单看⼀下Spring事务的使⽤⽅式,配置:<tx:annotation-driven transaction-manager="transactionManager"/><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>在需要开启事务的⽅法上加上@Transactional注解即可,这⾥需要注意的是,当标签在不指定transaction-manager属性的时候,会默认寻找id固定名为transactionManager的bean作为事务管理器,如果没有id为transactionManager的bean并且在使⽤@Transactional注解时也没有指定value(事务管理器),程序就会报错。
springmvc工作原理和源码分析
![springmvc工作原理和源码分析](https://img.taocdn.com/s3/m/4433e3df85254b35eefdc8d376eeaeaad1f3161a.png)
springmvc⼯作原理和源码分析springmvc⼯作原理以及源码分析(基于spring3.1.0) springmvc是⼀个基于spring的web框架.本篇⽂章对它的⼯作原理以及源码进⾏深⼊分析. ⼀、springmvc请求处理流程 ⼆、springmvc的⼯作机制 三、springmvc核⼼源码分析 四、谈谈springmvc的优化⼀、springmvc请求处理流程 引⽤spring in action上的⼀张图来说明了springmvc的核⼼组件和请求处理流程:①:DispatcherServlet是springmvc中的前端控制器(front controller),负责接收request并将request转发给对应的处理组件. ②:HanlerMapping是springmvc中完成url到controller映射的组件.DispatcherServlet接收request,然后从HandlerMapping查找处理request的controller. ③:Cntroller处理request,并返回ModelAndView对象,Controller是springmvc中负责处理request的组件(类似于struts2中的Action),ModelAndView是封装结果视图的组件. ④⑤⑥:视图解析器解析ModelAndView对象并返回对应的视图给客户端.⼆、springmvc的⼯作机制 在容器初始化时会建⽴所有url和controller的对应关系,保存到Map<url,controller>中.tomcat启动时会通知spring初始化容器(加载bean的定义信息和初始化所有单例bean),然后springmvc会遍历容器中的bean,获取每⼀个controller中的所有⽅法访问的url,然后将url和controller保存到⼀个Map中; 这样就可以根据request快速定位到controller,因为最终处理request的是controller中的⽅法,Map中只保留了url和controller中的对应关系,所以要根据request的url进⼀步确认controller中的method,这⼀步⼯作的原理就是拼接controller的url(controller上@RequestMapping的值)和⽅法的url(method上@RequestMapping的值),与request的url进⾏匹配,找到匹配的那个⽅法; 确定处理请求的method后,接下来的任务就是参数绑定,把request中参数绑定到⽅法的形式参数上,这⼀步是整个请求处理过程中最复杂的⼀个步骤。
SpringSecurity3源码分析-BasicAuthenticationFilter分析
![SpringSecurity3源码分析-BasicAuthenticationFilter分析](https://img.taocdn.com/s3/m/9ed8c56600f69e3143323968011ca300a6c3f6a7.png)
BasicAuthenticationFilter过滤器对应的类路径为org.springframework.security.web.authentication.www.BasicAuthenticationFilterBasic验证方式相比较而言用的不是太多。
spring security也支持basic的方式,配置如下<;security:http auto-config=";true";>;<;!-- <;security:form-login login-page=";/login.jsp";/>;-->;<;security:http-basic/>;<;security:logout logout-success-url=";/login.jsp"; invalidate-session=";true";/>;<;security:intercept-url pattern=";/login.jsp*"; filters=";none";/>;<;security:intercept-url pattern=";/admin.jsp*"; access=";ROLE_ADMIN";/>;<;security:intercept-url pattern=";/index.jsp*"; access=";ROLE_USER,ROLE_ADMIN";/>;<;security:intercept-url pattern=";/**"; access=";ROLE_USER,ROLE_ADMIN";/>; <;/security:http>;如果选择basic方式,需要把form-login标签的定义给注释掉。
SpringTask源码分析
![SpringTask源码分析](https://img.taocdn.com/s3/m/98663fe15ff7ba0d4a7302768e9951e79a896955.png)
SpringTask源码分析开头从功能上来说,spring-task这个组件主要包括了两个/两种功能:任务的定时调度/执⾏,对应xml配置的task:scheduler和task:scheduled-tasks标签。
⽅法异步执⾏,对应xml配置的task:executor标签。
task:annotation-driven标签被以上两种功能共有。
下⾯就这两种功能分别进⾏说明。
定时器⽤法以XML作为⽰例,基于注解的也是⼀样的。
<task:scheduler id="scheduler" pool-size="3" /><bean id="task" class="task.Task"/><task:scheduled-tasks scheduler="scheduler"><task:scheduled ref="task" method="print" cron="0/5 * * * * ?"/></task:scheduled-tasks>定义了⼀个定时任务,每隔5秒执⾏Task的print⽅法,Task:public class Task {public void print() {System.out.println("print执⾏");}}关于cron表达式可以参考:解析注册此部分的解析器注册由TaskNamespaceHandler完成:@Overridepublic void init() {this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());this.registerBeanDefinitionParser("executor", new ExecutorBeanDefinitionParser());this.registerBeanDefinitionParser("scheduled-tasks", new ScheduledTasksBeanDefinitionParser());this.registerBeanDefinitionParser("scheduler", new SchedulerBeanDefinitionParser());}schedulerSchedulerBeanDefinitionParser源码:@Overrideprotected String getBeanClassName(Element element) {return "org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler";}@Overrideprotected void doParse(Element element, BeanDefinitionBuilder builder) {String poolSize = element.getAttribute("pool-size");if (StringUtils.hasText(poolSize)) {builder.addPropertyValue("poolSize", poolSize);}}由于SchedulerBeanDefinitionParser是AbstractSingleBeanDefinitionParser的⼦类,所以Spring将task:scheduler标签解析为⼀个BeanDefinition。
springmvc源码解析
![springmvc源码解析](https://img.taocdn.com/s3/m/cfed20c959f5f61fb7360b4c2e3f5727a5e92447.png)
return this.context; } catch (RuntimeException | Error ex) {
logger.error("Context initialization failed", ex); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); throw ex; }
("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis();
try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown.
</context-param>
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup>
spring详解
![spring详解](https://img.taocdn.com/s3/m/7cb86a52804d2b160b4ec09b.png)
Spring详解标签:spring| 发表时间:2013-09-10 11:09 | 作者:Magneto7分享到:出处:Spring是什么Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目的是简化企业开发.IOC 控制反转public class PersonServiceBean {private PersonDao personDao = new PersonDaoBean();public void save(Person person){personDao.save(person);}}PersonDaoBean 是在应用内部创建及维护的。
所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。
这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。
依赖注入(Dependency Injection)当我们把依赖对象交给外部容器负责创建,那么PersonServiceBean类可以改成如下:public class PersonServiceBean {private PersonDao personDao ;//通过构造器参数,让容器把创建好的依赖对象注入进PersonServiceBean,当然也可以使用setter方法进行注入。
public PersonServiceBean(PersonDao personDao){this.personDao=personDao;}public void save(Person person){personDao.save(person);}}所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中。
为何要使用Spring至少在我看来,在项目中引入spring立即可以带来下面的好处降低组件之间的耦合度,实现软件各层之间的解耦。
springboot源码解读与原理分析
![springboot源码解读与原理分析](https://img.taocdn.com/s3/m/224a4537a200a6c30c22590102020740be1ecd1c.png)
springboot源码解读与原理分析spring boot 是spring家族中的一款框架,集持久层、视图层、服务层为一体,极大的减低了开发者在开发分析、实现、测试、部署以及维护上的工作量。
spring boot 的架构相比较传统的spring mvc框架简化了很多,采用的是一款简单的分布式server框架,使得开发可以专注于应用开发,而不是框架编程技术;而且通过几个简单的配置,就可以自动初始化和自动装配这些服务,减少了对于ssm架构中繁琐定制的配置。
spring boot 的实现原理主要在于spring 容器,spring boot 需要依赖spring 容器的自动初始化容器及bean,通过加载特殊的Spring 配置文件,可以加载所有的Bean,通过BeanFactory 接口,就可以获得想要的Bean。
另外,spring boot 还通过注解@EnableAutoConfiguration,可以自动完成项目的配置,该注解的作用是会根据不同的包路径自动引入对应的jar依赖,完成自动配置,这样不仅可以简化开发者的编码实现,而且可以节省很多时间。
spring boot,还可以使用嵌入式Web容器,通过这种方式,可以直接生成war文件,无需安装部署Web容器,而且可以通过嵌入式的服务器,在服务中实现高并发的处理,也可以在测试环境做一些调整,这样可以最大化,减少服务器的资源消耗,提高服务效率。
总之,spring boot采用了结合了spring 容器、注解、嵌入式Web容器的技术,为开发者提供了一款轻量级的快速开发框架,而且这种技术方案,在有多个应用时,可以大大提高开发效率,减少重复劳动,使得维护变得更简单,有助于改善应用质量以及提高开发效率。
Spring源码解析-Scopes之Request、Session、Applicatio...
![Spring源码解析-Scopes之Request、Session、Applicatio...](https://img.taocdn.com/s3/m/71854d246d85ec3a87c24028915f804d2b16878f.png)
Spring源码解析-Scopes之Request、Session、Applicatio...(给ImportNew加星标,提高Java技能)转自:开源中国,作者:麦克斯链接:/wang5v/blog/3017934Request、Session、Application概念在这篇Spring源码解析-Singleton Scope(单例)和Prototype Scope(多例)博客中介绍了2个比较常用的scope同时也简单的介绍了本篇博客要讲的这三个不常用的scope的概念,今天来详细揭开这3个很不常用的scope。
这三个只能用于web应用中,即要用于Web的Spring应用上下文(如:XmlWebApplicationContext),如果你用于非web应用中(如ClassPathXmlApplicationContext)是会抛出异常的。
Request Scope第一个要介绍的就是Request了,顾名思义,如果bean定义了这个scope,标示着这个bean的生命周期就是每个HTTP Request请求级别的,换句话说,在不同的HTTP Request请求中,Request Scope的bean都会根据bean的definition重新实例化并保存到RequestAttribute里面。
这也就是说,这个实例只会在一次请求的全过程中有效并可见,当请求结束后,这个bean就会被丢弃,生命周期很短的。
又因为每次请求都是独立的,所以你修改Request Scope的bean是只对内部可见,其他的通过相同的bean definition创建的实例是察觉不到的。
怎么去定义Request Scope呢?Spring提供了两种方式:一种XML方式配置:<bean id='testRequest' class='com.demo.TestRequest' scope='request'/>另外一种就是注解的方式:@RequestScope@Componentpublic class TestRequest{// ...}这样我们就指定了这个Bean的scope为Request的。
【java】【spring】源码分析,@AliasFor互为别名
![【java】【spring】源码分析,@AliasFor互为别名](https://img.taocdn.com/s3/m/b4f363fdf80f76c66137ee06eff9aef8941e4865.png)
【java】【spring】源码分析,@AliasFor互为别名在spring中,最常见的⼀个注解AliasFor它的作⽤就是多个属性互为别名package org.springframework.core.annotation;import ng.annotation.Annotation;import ng.annotation.Documented;import ng.annotation.ElementType;import ng.annotation.Retention;import ng.annotation.RetentionPolicy;import ng.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})@Documentedpublic @interface AliasFor {@AliasFor("attribute")String value() default "";@AliasFor("value")String attribute() default "";Class<? extends Annotation> annotation() default Annotation.class;}就是说attribute和value的值是⼀样的,互为别名为什么需要互为别名呢?原因是当使⽤注解时,注解有value()属性,不指明具体名称时就默认是value我们常见的就是springMVC⾥⾯的@RequestMapping⼀般⽤@RequestMapping("xxx")这⾥默认就是@RequestMapping(value = "xxx")看RequestMapping源码,看到value和path是互为别名,如果不是互为别名,那么就要这样写@RequestMapping(path = "xxx")。
SpringSecurity3源码分析-RequestCacheAwareFilter分析
![SpringSecurity3源码分析-RequestCacheAwareFilter分析](https://img.taocdn.com/s3/m/9065e682dc88d0d233d4b14e852458fb770b38f5.png)
RequestCacheAwareFilter过滤器对应的类路径为org.springframework.security.web.savedrequest.RequestCacheAwareFilter这个filter的用途官方解释是用于用户登录成功后,重新恢复因为登录被打断的请求这个解释也有几点需要说明被打算的请求:简单点说就是出现了AuthenticationException、AccessDeniedException 两类异常重新恢复:既然能够恢复,那肯定请求信息被保存到cache中了首先看被打断请求是如何保存到cache中的实际上,上一篇的ExceptionTranslationFilter分析已经提到了requestCache.saveRequest(request, response)是的,如果出现AuthenticationException或者是匿名登录的抛出了AccessDeniedException,都会把当前request保存到cache中。
这里的cache是HttpSessionRequestCache,接着看HttpSessionRequestCache的saveRequest方法public void saveRequest(HttpServletRequest request, HttpServletResponse response) {//由于构造HttpSessionRequestCache的bean时,没有设置justUseSavedRequestOnGet属性,所以该属性为默认值false。
if (!justUseSavedRequestOnGet || ";GET";.equals(request.getMethod())) { //构造DefaultSavedRequest,并且设置到session中DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, portResolver);if (createSessionAllowed || request.getSession(false) != null) {request.getSession().setAttribute(DefaultSavedRequest.SPRING_SECURITY_SAVED_REQU EST_KEY, savedRequest);}}}这里应该知道,实际上被打断的请求被封装成DefaultSavedRequest对象保存到session中了分析完保存被打断的请求,接着就分析如何恢复被打断的请求了。