Spring学习笔记三
6、依赖注入
6.1、Set方式注入【重点】
- 依赖注入:Set注入!
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象中的所有属性,由容器来注入!
【环境搭建】
-
复杂类型
public class Address { private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
-
真实测试对象
public class Student { private String name; private Address address; private String[] books; private List<String> hobbys; private Map<String, String> card; private Set<String> games; private String wife; private Properties info; }
-
beans.xml
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.zkb.entity.Student"> <!--第一种 普通值注入 用value --> <property name="name" value="张三"></property> </bean> </beans>
-
测试类
public class MyTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student =(Student) context.getBean("student"); System.out.println(student.getName()); } }
-
完善注入信息
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="com.zkb.entity.Address"> <property name="address" value="西安"></property> </bean> <bean id="student" class="com.zkb.entity.Student"> <!--第一种 普通值注入 用value --> <property name="name" value="张三"></property> <!--第二种,Bean注入 用ref --> <property name="address" ref="address"></property> <!--数组注入 ref --> <property name="books"> <array> <value>西游记</value> <value>三国演义</value> <value>红楼梦</value> <value>水浒传</value> </array> </property> <!-- List注入 --> <property name="hobbys"> <list> <value>打球</value> <value>打游戏</value> <value>打屁屁</value> </list> </property> <!-- Map --> <property name="card"> <map> <entry key="身份证" value="1231242353451235321"/> <entry key="银行卡" value="123124123124123"/> <entry key="学号" value="12312413432412"/> </map> </property> <!-- Set --> <property name="games"> <set> <value>LOL</value> <value>DNF</value> <value>CSGO</value> </set> </property> <property name="wife"> <null/> </property> <!--Properties --> <property name="info"> <props> <prop key="学号">19030514118</prop> <prop key="性别">男</prop> <prop key="姓名">张三</prop> </props> </property> </bean> </beans>
6.2、拓展方式注入
我们可以使用P命名空间和C命名空间进行注入
官方解释:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUskiEKg-1635216086549)(C:\Users\86186\AppData\Roaming\Typora\typora-user-images\image-20211025123138124.png)]
使用:
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- P命名空间注入,可以直接注入属性的值 -->
<bean id="user" class="com.zkb.entity.User" p:name="赵康博" p:age="18">
</bean>
<!-- C命名空间注入,可以通过构造器注入 construct-args -->
<bean id="user2" class="com.zkb.entity.User" c:age="18" c:name="赵康"></bean>
</beans>
测试:
@Test
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("userbean.xml");
User user = context.getBean("user2",User.class);
System.out.println(user);
}
注意点:P命名和C命名空间不能直接使用,需要导入xml约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
6.3、bean的作用域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h18yQXIc-1635216086551)(C:\Users\86186\AppData\Roaming\Typora\typora-user-images\image-20211025155727170.png)]
-
单例模式(Spring的默认机制)
<bean id="user2" class="com.zkb.entity.User" c:age="18" c:name="赵康" scope="singleton"></bean>
-
原型模式:每次从容器中get的时候,都会产生一个新对象!
<bean id="user2" class="com.zkb.entity.User" c:age="18" c:name="赵康" scope="prototype"></bean>
-
其余的request、session、application 这些只能在WEB开发中使用。
7、Bean的自动装配
- 自动装配是Spring满足bean依赖的一种方式!
- Spring会在上下文中自动寻找,并自动给bean装配属性!
在Spring中,有三种装配的方式
- 在xml中显示的配置
- 在java中显示的配置
- 隐式的自动装配bean【重点】
7.1、测试
环境搭建:一个人有两个宠物
7.2、ByName自动装配
<!-- byName会自动在容器上下文查找,和自己对象set方法后面的值对应的beanid! -->
<bean id="people" class="com.zkb.pojo.People" autowire="byName">
<property name="name" value="赵康博"></property>
</bean>
7.3、byType自动装配(要全局唯一)
<bean class="com.zkb.pojo.Cat"></bean>
<bean class="com.zkb.pojo.Dog"></bean>
<!-- byName会自动在容器上下文查找,和自己对象set方法后面的值对应的beanid! -->
<!-- byType会自动在容器上下文查找,和自己对象属性类型相同的bean! -->
<bean id="people" class="com.zkb.pojo.People" autowire="byType">
<property name="name" value="赵康博"></property>
</bean>
小结:
- byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法值一致!
- byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!
7.4、使用注解实现
要使用注解须知:
-
导入约束: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
直接在属性上使用即可!也可以在set方式上使用!
使用Autowired我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byName!
科普:
@Nullablue 字段标记了这个注解,说明这个字段可以为NULL;
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入!
public class People {
@Autowired
@Qualifier(value="cat111")
private Cat cat;
@Autowired
@Qualifier(value="dog222")
private Dog dog;
private String name;
}
@Resource注解
public class People {
@Resource
private Cat cat;
@Resource
private Dog dog;
}
小结:
@Resource和@Autowired的区别与联系:
- 都是用来自动装配的,都可以放在属性字段上
- @Autowired 通过byName实现【常用】
- @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到就会报错!【常用】
- 执行顺序不同:@Autowired 通过byType实现。@Resource默认通过byName的方式实现。
8、使用注解开发
在Spring4之后,要使用注解开发,必须要保证aop的包导入
使用注解需要导入context约束,增加注解的支持!
-
bean
-
属性如何注入
//等价于在xml注册一个bean @Component public class User { //相当与property标签赋值 @Value("zkb") public String name; }
-
衍生的注解
@Component有几个衍生注解,我们在Web开发中,会按照mvc三层架构分层
-
dao【@Repository】
-
service【@Service】
-
controller【@Controller】
这四个注解功能一样,都是代表将某个类注册到Spring中,装配bean
-
-
作用域
@Scope("prototype")
-
小结
xml与注解:
- xml更加万能,适用于任何场合!维护简单方便
- 注解 不是自己类使用不了,维护相对复杂!
xml与注解最佳结合:
-
xml用来管理bean
-
注解只负责完成属性的注入
-
我们在使用的过程中,只需要注意:必须让注解生效,就需要开启注解的支持
<!-- 指定要扫描的包,这个包下的注解就会生效 --> <context:component-scan base-package="com.zkb"> </context:component-scan> <context:annotation-config/>
9、使用Java的方式配置Spring
我们现在要完全不适用Spring的xml配置了,全权交给java做!
JavaConfig是Spring的一个子项目,在Spring4之后,它成为了一个核心功能
实体类:
//这里的注解的意思是,就是说明这个类被Spring接管了,即注册到了容器中
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("康康")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [name=" + name + "]";
}
}
配置文件:
//这个注解也会被Spring容器托管,因为他本来就是一个@Component @configuration代表这是一个配置类
@Configuration
@ComponentScan("com.zkb.pojo")
@Import(MyConfig2.class)
public class MyConfig {
//注册一个bean 相当于我们之前写的一个bean标签
//这个方法的名字 就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User getUser() {
return new User();
}
}
测试类:
public static void main(String[] args) {
//如果完全使用配置类方式去做,我们就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("user",User.class);
System.out.println(user.getName());
}
这种纯java的配置方式,在SpringBoot中随处可见!
值,就相当于bean标签中的class属性
@Bean
public User getUser() {
return new User();
}
}
测试类:
```java
public static void main(String[] args) {
//如果完全使用配置类方式去做,我们就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载!
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("user",User.class);
System.out.println(user.getName());
}
这种纯java的配置方式,在SpringBoot中随处可见!