Spring学习笔记1
IOC 创建对象的方式
1.默认使用无参构造创建对象
2.使用有参构造创建对象:
第一种根据index参数下标设置
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="kuangshen2"/>
</bean>
第二种根据参数名字设置
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="kuangshen2"/>
</bean>
第三种根据参数类型设置(不推荐使用)
<bean id="userT" class="com.kuang.pojo.UserT">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>
Spring配置
1.别名
- id是bean的唯一标识符号,若没有Id那么name为默认标识符号
如果配置了id又配置了name,那么name为别名,别名可以配置多个,这些别名用逗号、空格和分号隔开 - 还可以通过标签配置别名,name传入需要配置的bean的id或者name,alias为别名,同样可以是多个,用逗号或者空格隔开
- 如果不给bean配置id和name只配置了class,那么可以通过ApplicationContext.getBean(Class)函数获取bean
2.Bean的配置
id:是bean的唯一标识符号
class:bean对象所对应的全限定名:包名+类型
name:也就是别名,别名可以配置多个,这些别名用逗号、空格和分号隔开
3.import
一般用于团队开发使用,可以将多个配置文件,导入合并为一个
依赖注入
1.构造器方式注入
有参构造、无参构造
2.set方法注入【重点】
<!-- 第一种,普通值注入,value-->
<property name="name" value="小卷"/>
<!-- 第二种,Bean注入,ref-->
<property name="address" ref="address"/>
<!-- 数组 -->
<property name="books">
<array>
<value>达摩流浪者</value>
<value>刀锋</value>
<value>一声所寻不过爱与自由</value>
<value>月亮与六便士</value>
<value>狂人日记</value>
</array>
</property>
<!-- list -->
<property name="hobbys">
<list>
<value>骑马</value>
<value>射箭</value>
<value>唱歌</value>
<value>跳舞</value>
</list>
</property>
<!-- Map -->
<property name="card">
<map>
<entry key="身份证" value="5123215215213"/>
<entry key="银行卡" value="9364796441"/>
<entry key="学生卡" value="33259654112"/>
<entry key="信用卡" value="799856314"/>
</map>
</property>
<!-- Set -->
<property name="games">
<set>
<value>LOL</value>
<value>GTA</value>
<value>WOW</value>
</set>
</property>
<!-- null -->
<property name="wife">
<null></null>
</property>
<!-- Properties -->
<property name="info">
<props>
<prop key="driver">aaddd</prop>
<prop key="url">wweee</prop>
<prop key="passwd">123456</prop>
<prop key="username">mmkk</prop>
</props>
</property>
3.扩展方式注入
可以使用p命名空间和c命名空间进行注入
需要导入官方xml配置:
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
p命名空间是set注入的一种快捷实现方式,需要注意以下几点:
- 实体类中必须有set方法
- 实体类中必须有无参构造器(默认存在)
- 导入p命名空间注入方式依赖
<!-- p命名空间注入,可以直接注入属性的值:property-->
<bean id="user" class="com.NATE.pojo.User" p:age="18" p:name="小卷"/>
c命名空间是构造器注入的一种快捷实现方式,需要注意以下几点:
- 实体类中必须存在有参构造器
- 必须导入c命名空间注入方式依赖
<!-- c命名空间注入,通过构造器注入:construct-args-->
<bean id="user2" class="com.NATE.pojo.User" c:age="100" c:name="小冬" scope="prototype"/>
Bean的作用域
1.单例模式
全局共享一个对象(Spring默认机制)
只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例
<bean id="user2" class="com.NATE.pojo.User" c:age="100" c:name="小冬" scope="singleton"/>
2.原型模式
每次从容器get的时候,都会产生一个新对象
<bean id="user2" class="com.NATE.pojo.User" c:age="100" c:name="小冬" scope="prototype"/>
其余request、session、application,这些只能在web开发中使用
Bean的自动装配
- 自动装配是Spring满足bean依赖一种方式
- Spring会在上下文中自动寻找,并自动给bean装配属性
在Spring中有三种装配的方式
1.在xml中显示的配置
2.在java中显示配置
3.隐式的自动装配bean【重要】
byName自动装配
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应对的beanid
<bean id="user" class="com.NATE.pojo.User" autowire="byName">
byType自动装配
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean
<bean id="user" class="com.NATE.pojo.User" autowire="byType">
小结
- byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
- byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
使用注解进行自动装配
注解优于xml
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.
使用注解须知:
- 导入约束:context约束
- 配置注解的支持:context:annotation-config/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired
- @Autowired默认先按byType进行匹配,如果发现找到多个bean,则又按照byName方式进行匹配,如果还有多个,则报出异常。
- 直接在属性在使用即可,也可以在set方式上使用
使用Autowired,可以不用编写Set方法,前提是这个自动装配属性在IOC(Spring)容器中存在,且符合名字
小知识点:
- @Nullable 字段标记了这个注解,说明这个字段可以为null;
- @Auwowired 方法默认为true;
如果显示定义了Autowired的required属性为falase,说明这个对象可以为null,否则不允许为空
public @interface Autowired {
boolean required() default true;
}
@Autowired(required = false)
- 如果@Autowired自动装配的环境比较复杂,无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value = “xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入
@Qualifier(value = "xxx")
@Resource (java注解)
- @Resource默认按byName自动注入
- 既不指定name属性,也不指定type属性,则自动按byName方式进行查找。如果没有找到符合的bean,则回退为一个原始类型进行进行查找,如果找到就注入
- 只是指定了@Resource注解的name,则按name后的名字去bean元素里查找有与之相等的name属性的bean
- 只指定@Resource注解的type属性,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入,使用注解需要导入context约束,增加注解的支持
1.bean
@Component:组件,放在类上,说明这个类被Spring管理了,就是bean
2.属性如何注入
@Value:
- 相当于
<property name="name" value="xxx">
; - 适合简单的情况配置,复杂情况还是要通过配置文件
- Set方法同样也可以注入
3.衍生的注解
@Component 有三个衍生注解,在web开发中,会按照mvc三层架构分层:
- @Controller (注入服务)
- @Service (注入dao)
- @Repository(实现dao访问)
这四个注解功能都是一样的,都是表示将某个类注册到Spring中,装配Bean
4.自动装配置
- @Autowired:自动装配通过类型、名字。如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value=“xxx”)
- @Nullable:字段标记了这个注解,说明这个字段可以为null;
- @Rescource:自动装配通过名字、类型
5.作用域
@Scope:默认是单例模式,即scope=“singleton”。
另外scope还有prototype(原型模式)、request、session、global session作用域。
6.小结
xml和注解:
- xml更加万能,适合于任何场所,维护简单方便;
- 注解,不是自己的类使用不了,维护想对复杂;
xml和注解最佳实践:
- xml用来管理bean;
- 注解只负责完成属性的注入
使用过程中,需要注意一个问题:必须让注解生效,需要开启注解的支持
<!-- 指定要扫描的包,这个包下面的注解就会生效 -->
<context:component-scan base-package="com.NATE.pojo"/>
<context:annotation-config/>
使用Java的方式配置Spring
// @Configuration代表一个配置类,相当于beans.xml;
// 归Spring容器托管,注册到容器中,因为它本身就是一个@Component
@Configuration
@ComponentScan("com.NATE.pojo")
@Import(Myconfig2.class) // 导入另外一个配置类
public class Myappconfig {
// 注册一个bean,相当于xml中的bean标签
// 方法的名字,相当于bean标签中的id属性
// 方法的返回值,相当于bean标签中的class属性
@Bean
public User user(){
return new User(); // 返回要注入到bean的对象
}
}
// 如果完全使用了配置类方式去实现,就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
ApplicationContext context = new AnnotationConfigApplicationContext(Myappconfig.class);
User getuser= context.getBean("user",User.class);
System.out.println(getuser.getName());