Spring框架学习

谈到Spring,大家都接触过,也都在用,但是到了解到什么水平各有高低。

说起spring的特点,大家张口就来,最常见的三个重要功能就是:
IOC:控制反转:将管理对象的权利由开发者交给了spring框架,Spring把这些类称为bean并统一管理。

DI:依赖注入:spring提供了一系列注解:@Controller等,让这些类可以被识别成bean,并通过@Autowried等注解声明直接找到相应的bean并直接使用。

AOP:面向切面:相同的逻辑方法会被我们抽取出来做成工具类,对代码来说相同的逻辑处理也可以被抽取出来,例如对系统做日志,事务管理,安全管理等需求,可以通过spring类进行统一管理,这就是aop。


Spring的优点:当然是对象的管理。

无spring管理情况下:new 一个类的对象来用。调用类负责被调用类的生命周期。
有spring管理情况下:将类作为bean进行管理,配置类扫描所有被标记为bean的类,使用时先建立上下文对象,使用上下文对象来getBean。

new对象造成代码耦合,资源冗余;
而spring创建的bean对象都是单例的,一个被标记为bean的对象或方法,只有第一次被调用时,会执行该对象的构造器内或方法内的全部过程,之后每次被调用都直接返回最后结果,中间过程不会再重复。


那么Spring是怎么把类装配成对象的:
1·首先,Spring管理类的地方叫做容器。容器里初始化之前啥也没有,想要容器里放入哪些类来作为bean是由我们决定的:
2·有一个注解@ComponentScan(value="com.xx")为自动扫描包下所有类(JAVA配置的写法,XML写法不尽相同);
3·然后在日常开发中,我们会将一些需要设置为bean的对象用注解标好;
   例如spring指定@Controller,@Service,@Repository,@Component等修饰的类或方法用来标注类;
4·在初始化时,spring会把@ComponentScan扫描的包下的所有被指定注解标识的类或方法加入到容器内进行管理,供我们使用。

而容器的抽象化对象叫做上下文。
① AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载上下文定义,适用于java注解的方式;
② ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式;
③ FileSystemXmlApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义,也就是说系统盘符中加载xml配置文件;
④ AnnotationConfigWebApplicationContext:专门为web应用准备的,适用于注解方式;
⑤ XmlWebApplicationContext:从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式。

例子:
//加载项目中的spring配置文件到容器
ApplicationContext context = new ClassPathXmlApplicationContext("resouces/applicationContext.xml");
new出上下文对象的同时,也是加载spring容器的时候。
而之后通过getBean可以取到相应的bean的对象。
User user = context.getBean(User.class);
这也是日常开发中,在工具类中调用bean的一个思路。


Spring装配bean对象时,有三种方法:
1·自动装配
    自动装配又分为组件扫描和自动装配两块:
    A·组件扫描:
    就是扫描项目内所有的bean来进行装配,有两种扫描方法:分为java注解(也就是上面说的上面说的基于@ComponentScan(value="com.xx")来扫描)或者XML配置(<context:component-scan base-package="xx/xx/"/>)
    这里有一点要注意:@ComponentScan不带后面参数时,只扫描自己本包及子包的bean,其他bean并不会被管理,因此需要指定包名。
    B·自动装配:当我们生命的bean对象A中关联着对象B时,这种依赖关系也会被spring管理。
    例如A中的构造函数调用了对象B,那么我们用spring自动声明A时,B也会被创建。
    引申:当A中调用的对象B为多态情况下,则spring不会去自动选择默认的实现对象,因此我们可以使用 @Primary来修饰我们想调用的实现对象上,spring优先调用有此注解的关联Bean。        
    自动化配置在面对调用第三方Jar的时候无法使用,因此延伸出了显性的去进行配置这条路。这条路又可以通过Java注解配置或XML配置类实现。    
2·Java注解
    即创建一个配置类,用@Configuration来进行修饰,然后我们在配置类内部去手写new一个类并手动给它架上Bean,这样它就会认为自己是个成熟的Bean了。
    当然我们也可以通过这种方式@Bean(name = "xxx")给它起一个帅气的名字。
    
    
3·XML配置
    XML配置就是大家都喜闻乐见的,最古老的配置方式了。通过创建一个XML,手动简历<bean>来进行构成。通过id类标识自己,通过ref来指向依赖。

基于以上情况,一般都会创建一个比所有配置都更高层次的根配置类/文件,该配置不声明任何的bean,只用来将多个配置组合在一起,从而让配置更易于维护和扩展。

 

 

用idea开发springboot项目时遇到了一个问题,如果我在serviceImpl类里用@Autowired来注解Dao,则dao的实例对象名会红线报错。
这个错误只是一个提示,并不影响使用,同样场景在eclipse编译下不会出现。
后来我发现原因是:在dao的接口上注解用的是@Mapper。这是一个mybatis项目。省去了mapper.xml的步骤,用@Autowired来实现bean的自动注入。
如果在Dao上使用了@Repository("/xxDao")或者@Repository,那么serviceimpl里的dao实例名则不会报错,因为他通过@Repository找到了自己的注入匹配。

这里引申开就是关于spring的一些注解 :
@Autowried:自动寻找符合修饰名称的Bean 
@Controller:修饰的bean是一个控制层类
@Service::修饰的bean是一个业务层类
@Repository: 修饰的bean是一个持久层类
@Component:修饰的对象是一个bean

@Configuration:这是一个配置类

@ResponseBody:
    @Responsebody 注解表示该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中,一般在异步获取数据时使用,
    通常是在使用 @RequestMapping 后,返回值通常解析为跳转路径,加上 @Responsebody 后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中。
    例子:未配置该注解情况下,返回值若为String,则会跳转到包含String的url去    
@RequestBody:
    获取request请求body中传来的值,根据值得格式进行判断:
    POST方法:如果格式为application/x-www-form-urlencoded则不用,除了文件上传格式multipart/form-data,其他格式均必须。
    GET方法下:除了上传文件格式,其他均必须。
@RequestMapping:
    放在类或方法上来表明url请求路径

@Param
@PathVariable:
    带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义。

通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过
@PathVariable("xxx") 绑定到操作方法的入参中。
    问题一:若传递的参数内含多个小数点 从第二个开始会被截取丢失,因此要在参数名后加上.+符号,例子:{version}换成{version:.+},或者在参数这一层后再加一层任意字符/xx/{version}/无意义字符串
    问题二:同时传多个参数,可以写成/xx/{1}/{2}这样
    问题三:@PathVariable不允许参数为空
    
    例子:不能允许为空,但是可以变通。最近遇到个required=false没用的情况。如下:
    @RequestMapping(value = "/student/{id}", RequestMethod.GET)
    public Student student(@PathVariable(required = false) Integer id) {
        //......
        return student;
    }
    按照上面的代码,是希望如果不传id,Integer id的id就为null,可以查询所有学生信息。但是发现,/student这个请求是过不来的,而且会报错。
    试了n次,突然发现,其实/student和/student/{id}是两个不同的url,当然是不能走同一个请求的呀。于是想到@RequestMapping是可以处理多个url的。
    于是将上面的@RequestMapping改成下面这样:
    @RequestMapping(value = {"/student/{id}", "/student"}, RequestMethod.GET)
    这样就是可以的,此时的required = false就可以起作用了。
    我觉得springmvc处理这块的逻辑就是:如果required = false,而你没有传这个参数,那么它会去找这个参数去掉之后的替代url (/student),
    如果发现有替代的url,就可以处理这个请求,如果没有找到,就抛出异常不去处理。
   


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值