spring依赖注入
依赖:bean对象的创建依赖于Spring容器
注入:bean对象的属性,由容器注入
spring项目创建流程:
- 新建项目,导入依赖(spring-webmvc:包含了所有需要的包)
- 编写读取配置文件(xml方式,也可java配置),新建pojo类
//获取spring的上下文对象,读取配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
-
public class Hello { private String str; public void setStr(String str) { this.str = str; } public String getStr() { return str; } public Hello() { } public Hello(String str) { this.str = str; } @Override public String toString() { return "Hello{" + "str='" + str + '\\'' + '}'; } }
- 编写配置xml文件,将bean注入容器,将属性注入容器
-
<!-- 使用spring创建对象,在spring中这些都成为bean 类型 变量名 = new 类型(); Hello hello = new Hello(); class = new 的对象 id = 变量名 注意:在这使用property时,bean中必须要有set方法 name 可以设置这个对象的别名 且可以设置多个别名 --> <!--property中的value指向一个具体的值,还可以ref指向一个对象--> <bean id="hello" class="pojo.Hello" name="hello2,hello3 hello4;hello5"> <property name="str" value="Spring"/> <!--构造器注入,index为构造方法的参数下标--> <constructor-arg index="0" value="123"/> </bean> <!--配置别名,取对象的时候可以使用--> <alias name="hello" alias="helloAlias"/>
- 编写测试类
-
@Test public void test(){ //获取spring的上下文对象,读取配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //使用容器中的bean对象 Hello hello = (Hello) context.getBean("hello"); System.out.println(hello.toString()); }
非自动装配配置文件详细说明
-
<?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"> <!--项目有不同的人开发,可以写多个配置文件,然后import--> <!--如果内容相同,会被合并为一个对象,可以使用多个别名引用--> <import resource="bean.xml"/> <!--依赖:bean对象的创建依赖于容器 注入:bean对象的属性,由容器注入 --> <!--注入,通过set方法注入 https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies --> <bean class="pojo.Address" name="address"> <property name="addressName" value="浙江工商大学"/> </bean> <bean class="pojo.Student" name="student"> <!--普通注入--> <property name="name" value="牛啊"/> <!--bean对象注入--> <property name="address" ref="address"/> <!--数组注入--> <property name="books"> <array> <value>数据结构</value> <value>面向对象</value> </array> </property> <property name="hobbies"> <list> <value>听歌</value> <value>敲代码</value> </list> </property> <property name="cards"> <map> <entry key="学生卡" value="1234"/> <entry key="地址" value-ref="address"/> </map> </property> <property name="games"> <set> <value>CF</value> </set> </property> <!--null注入--> <property name="wife" > <null/> </property> <!--property注入--> <property name="properties"> <props> <prop key="学号">123456</prop> <prop key="nn">111</prop> </props> </property> </bean> <!--p命名标签 通过set方法注入,需要p标签约束 The p-namespace lets you use the bean element’s attributes (instead of nested <property/> elements) to describe your property values collaborating beans, or both. --> <bean name="teacher" class="pojo.Teacher" p:name="老师"/> <!--c标签,必须要有构造器,通过构造器注入,需要c标签约束 Similar to the XML Shortcut with the p-namespace, the c-namespace, introduced in Spring 3.1, allows inlined attributes for configuring the constructor arguments rather then nested constructor-arg elements. --> <!--_0是构造方法的第一个参数--> <bean class="pojo.Boss" name="boss" c:_0="bossName" c:_1="2"/> <!--作用域--> <!--默认单例模式:即容器中只有一个实例,无论使用多少次,都使用同一个实例--> <bean class="pojo.Boss" name="boss1" c:_0="bossName" c:_1="2" scope="singleton"/> <!--原型模式:每次从容器中获取的时候,都会新产生一个对象--> <bean class="pojo.Boss" name="boss2" c:_0="bossName" c:_1="2" scope="prototype"/> </beans>
- 测试单例属性
-
@Test public void testStudent(){ //获取spring的上下文对象,读取配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //使用容器中的bean对象 Student student = (Student) context.getBean("student"); System.out.println(student.toString()); Teacher teacher = (Teacher) context.getBean("teacher"); System.out.println(teacher.toString()); //作用域单例模式 Boss boss = (Boss) context.getBean("boss"); System.out.println(boss.toString()); Boss boss1 = (Boss) context.getBean("boss1"); Boss boss11 = (Boss) context.getBean("boss1"); System.out.println(boss1 == boss11); //作用域原型模式 Boss boss2 = (Boss) context.getBean("boss2"); Boss boss21 = (Boss) context.getBean("boss2"); System.out.println(boss2==boss21); }
自动装配@AutoWired:在配置bean的时候,如果属性是个对象需要引用另一个对象,不需要在property标签中引用
-
<!--自动装配:spring自动寻找bean,自动装配bean到容器--> <bean name="cat" class="pojo.autowired.Cat"/> <bean name="dog" class="pojo.autowired.Dog"/> <!--autowire : byName:会自动再容器中找和自己对象set方法后面值对应的beanid ,找到这个name对应的bean,这样就不用了再写property属性了 需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法一致 byType: 会自动再容器中找和自己对象属性类型相同的bean ,找到这个name对应的bean,但多个相同bean就会出错。 需要保证bean的class唯一,并且这个bean需要和对象属性的类型相同 --> <bean name="person" class="pojo.autowired.Person" autowire="byName"> <property name="name" value="牛啊"/> </bean>
-
@Data//自动创建set get 方法等 public class Person { @Autowired(required = false) //使用required此属性可以为空 private Dog dog; @Autowired private Cat cat; private String name; }
自动装配,使用注解
-
<?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"> <!--使用注解实现自动装配,jdk1.5,spring2.5支持注解--> <!--加上这个即可--> <context:annotation-config/> <bean id="cat" class="pojo.autowired.Cat"/> <bean id="cat1" class="pojo.autowired.Cat"/> <bean id="dog" class="pojo.autowired.Dog"/> <!--autowire : byName:会自动再容器中找和自己对象set方法后面值对应的beanid ,找到这个name对应的bean,这样就不用了再写property属性了 需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法一致 byType: 会自动再容器中找和自己对象属性类型相同的bean ,找到这个name对应的bean,但多个相同bean就会出错。 需要保证bean的class唯一,并且这个bean需要和对象属性的类型相同 --> <!-- 在Person类中,Cat和Dog属性上加上@AutoWired 即可 @AutoWired可以在属性上使用,也可以在set上使用 使用@AutoWired我们可以不同编写set方法,前提是这个自动装配在IOC(spring)容器中存在, 且bean的name/id符合名字byName中的Name @AutoWired(require = true):此注入属性可以为空,默认为false **不用@AutoWired可以使用@Resource 都是实现自动装配 @AutoWired通过byType的方式实现,必须要有这个对象存在【常用】 @Resource 默认使用ByName的方式实现,如果找不到名字再用ByType,两个都找不到报错 --> <bean id="person" class="pojo.autowired.Person"/> </beans>
@Data
public class Person {
//@Autowired(required = false) //使用required此属性可以为空
@Resource(name = "dog")
private Dog dog;
@Autowired
@Qualifier(value = "cat1") //可以指定一个唯一的对象注入
private Cat cat;
@Value("nameStr") //可以注入属性值,复杂属性使用xml较好
private String name;
自动扫包,注入(注意dtd约束)
-
<?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:component-scan base-package="pojo.component"/> <!--使用注解实现自动装配,jdk1.5,spring2.5支持注解--> <!--加上这个即可--> <context:annotation-config/> </beans>
-
package pojo.component; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * @Author: nsk * @Description: * @Date: create in 2021/4/11 14:05 */ //Component放到类上,说明这个类被Spring管理了 @Component @Data public class User { //自动注解属性 @Value("牛啊") private String name; }
-
@Nullable 相当于@AutoWired的require属性
-
@Component 组件,放在类上,说明这个类被Spring管理了,就是bean,衍生注解 在mvc架构分层的时候
-
dao:使用@Resposutory,和@Component功能相同
-
service:使用@Service,和@Component功能相同
-
controller: @Controller ,和@Component功能相同
-
四个注解功能一样,都是将谋个类,注册到spring容器中
-
@Scop(“prototype”):在类名上使用,单例模式,是否每次调用都重新新建对象
java方式依赖注入bean
- 编写配置类:
-
package config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import pojo.component.User; /** * @Author: nsk * @Description: * @Date: create in 2021/4/11 14:39 */ /** * - @configuration :在配置的类上 * - @ComponentScan :扫描包 * - @Import: 导入其他包 */ @Configuration //这个也会被Spring容器托管,注册到容器中 @ComponentScan("pojo.component") public class Nconfig { //注册一个bean.相当于xml中的bean标签 //方法的名字相当于bean中的id属性 //返回值相当于class类型 @Bean public User user(){ return new User(); } }
- 使用:
-
@Test public void testJavaConfig(){ //如果完全使用配置类方式去做,我们就只能通过AnnotationConfig上下文去获取容器,通过配置类的class对象加载! ApplicationContext context = new AnnotationConfigApplicationContext(Nconfig.class); User user = context.getBean("user",User.class); System.out.println(user); }