Spring理解1 ioc
Spring
Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器(框架)。
需要了解
ioc容器
IOC底层原理
IOC接口 BeanFactory
Bean的作用域
IOC操作Bean管理(基于xml)
IOC操作Bean管理(基于注解)
IOC概念和原理
控制反转 降低代码之间的耦合度
把对象创建和对象之间调用过程全交给spring 管理
使用ioc目的是降低耦合度
在Java基础中 我们通常创建多个类,在一个类中调用其他的类的方法需要实现一下方式
创建UserDao接口
public interface UserDao {
public void Trick();
}
创建一个实现接口的类
public class UserDaoImpl implements UserDao{
@Override
public void Trick() {
System.out.println("我是石大炮 我想trick....");
}
}
再创建另一个UserService接口
public interface UserService {
public void cick();
}
实现接口方法
public class UserServiceImpl implements UserService {
UserDao userDao=new UserDaoImpl();
@Override
public void cick() {
userDao.Trick();
}
}
最后添加测试类
public class TestService {
@Test
public void Test1(){
UserService userService=new UserServiceImpl();
userService.cick();
}
}
结果:我们在UserServiceImpl实现类中成功调取了UserDaoImpl中的方法
这种方式耦合度太高 ,一旦一个类的方法或属性发生改变,其他的类也需要更改,正所谓牵一发而全身,我们是否可以解决这个问题呢?
IOC容器的概念和原理
IOC 叫做控制反转其实和DI 依赖注入的功能相同,如果我们将对象的创建交给第三方组件来管理,当我创建的某个类需要另外的对象的时候,我们直接利用第三方组件来对他进行创建交给他。
Spring容器(ioc)就是一个容器组件负责帮我们管理。当UserDaoImpl类需要UserServiceImpl类中的对象时,如果UserServiceImpl类已经声明了交给Spring容器管理的情况下,那么程序在运行到类UserDaoImpl类需要UserServiceImpl类时候,Spring容器就通过依赖注入的方式将器对象注入到另一个类中来协助完成任务。
我们通过第三方的依赖注入,对象就不需要自行的创建和管理类与类之间的关系。
对象的创建依赖注入有多种:接口注入 ,构造方法注入,setter方法注入等等来减少代码组件中的耦合度
所谓ioc的控制反转其实就是当初是我来实现创建和管理对象之间的关系的,而现在出现了ioc容器,那我就可以直接当撒手掌柜,将这份权力交给ioc容器,让他实现我当初要干的苦活累活。这就是所谓的控制反转---控制权的反转。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
IOC说到底就是一个容器,但是如何向容器中放入我们的需要让他给我们管理的对象呢?涉及到Spring的应用上下文!
应用上下文 即是spring容器的抽象化表述。Spring核心是容器但是容器并不唯一,我们需要实现容器,所以需要应用上下文的存在
ioc容器底层就是对象工厂
此处只讨论第二个,第一个用的不多。ApplicationContext从一个或多个基于java配置类中加载上下文定义,适用于java注解方式
以下是不同常见下选择的应用上下文来对于容器的实现:
① AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载上下文定义,适用于java注解的方式;
② ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式;
③ FileSystemXmlApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义,也就是说系统盘符中加载xml配置文件;
④ AnnotationConfigWebApplicationContext:专门为web应用准备的,适用于注解方式;
⑤ XmlWebApplicationContext:从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式。
ioc实现步骤:
第一步 导入jar包maven
第二步 xml配置文件 配置创建的对象
第三步 有Service和Dao类 创建工程类
第四步将我们需要管理的对象(我们称之为bean)bean之间协作关系配置好,然后利用配置上下文加载到我们的Spring容器 容器就能给我们提供服务了
演示:
首先创建一个类
public class Person {
String name;
int age;
String gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public void Cry(){
System.out.println("我为我叫石大炮而感到悲伤....");
}
}
第二步在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"
xmlns:p="http://www.springframework.org/schema/beans/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 创建对象-->
<bean id="person" class="com.atqijie.spring5.collectiontype.Person">
<!-- 配置属性注入-->
<property name="name" value="石大炮"/>
<property name="age" value="22"></property>
<property name="gender" value="男"></property>
</bean>
</beans>
第三步利用应用上下文将配置加载到ioc容器中让spring替我们管理对象 ,在我们需要对象的时候再通过容器中获取就可
package Test;
import com.alibaba.druid.sql.ast.ClusteringType;
import com.atqijie.spring5.collectiontype.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test2 {
@Test
public void TestPerson(){
// 提供应用上下文将配置加载到ioc容器 让Spring替我们管理对象 待我们需要对象的时候直接从从容器中获取即可
ApplicationContext context= new ClassPathXmlApplicationContext("bean1.xml");
// 我们从容器中获取我们想要的对象
Person person=context.getBean("person", Person.class);
person.Cry();
int personAge= person.getAge();
String personName=person.getName();
String personGender=person.getGender();
System.out.println(personName);
System.out.println(personGender);
System.out.println(personAge);
}
}
结果:
由上我们实现了在spring中创建对象,对象的属性同样由容器配置。我们将对象创建的主动性交给了spring容器,程序被动的接受了对象并没有像往常一样创建对象 即 实现了控制反转 也称控制权反转(个人理解)
重点细节:
IOC管理bean的两种方式(创建需要的对象和对其属性进行配置)
1 xml配置文件方式来实现(上述即xml配置文件方式实现)//用的不多建议 听说面试问的比你用的多?
2基于注解方式来实现
3创建对象注入属性方式有多种 构造方法,使用set等创建对象和属性初始化
1xml配置文件方式实现:
1.1 利用xml配置文件来创建对象
<bean id="person" class="com.atqijie.spring5.collectiontype.Person">
1.1.2基于xml方式注入属性
!-- 配置属性注入-->
<property name="name" value="石大炮"/>
<property name="age" value="22"></property>
<property name="gender" value="男"></property>
依赖注入:通过构造方法和set方法来进行依赖注入(设置属性初始化)
1构造方法的方式进行依赖注入
1无参构造
创建Animal类
package com.atqijie.spring5.collectiontype;
public class Animal {
String name;
int age;
public Animal() {
System.out.println("这是一个无参构造的方法");
}
public void Do(){
System.out.println("我是胖虎你是静香吗.....?");
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
创建对象
<bean id="animal" class="com.atqijie.spring5.collectiontype.Animal">
<property name="name" value="胖虎"></property>
<property name="age" value="22"></property>
</bean>
利用应用上下文将我们的配置加载ioc容器中,测试一下
@Test
public void TestAnimal(){
ApplicationContext context=new ClassPathXmlApplicationContext("bean1.xml");
Animal animal=context.getBean("animal",Animal.class);
animal.Do();
}
结果
我们知道了在我们调取Do方法之前,我们的无参构造方法已经创建了Animal对象
2有参构造来创建
public class Dog {
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public Dog() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void check(){
System.out.println("我是静香啊..."+name);
}
}
xml编写 分几种
第一种 根据名称来设置属性
<bean id="dog" class="com.atqijie.spring5.collectiontype.Dog">
<constructor-arg name="name" value="胖虎"></constructor-arg>
第二种根据index 下标设置属性
<!--index =0是第一个值 index=1 是第二个值 都是判断第几个的 一般直接使用名称来找 -->
<!-- <constructor-arg index="0" value="胖虎"/>-->
第三种根据参数类型设置属性
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.atqijie.spring5.collectiontype.Dog">
<constructor-arg type="java.lang.String" value="小夫"/>
</bean>
测试一下
@Test
public void TestDog(){
ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
Dog dog=context.getBean("dog",Dog.class);
dog.check();
}
结果


结果:
2.2如何注入属性
<bean id="UserService " class="com.atqijie.spring5.Service.UserService ">
<!-- 在service层中注入userDao对象 name 是类里面的属性名称 ref属性指的是创建UserDao对象bean标签的id值-->
<!-- 用到ref表示把外部bean注入进来表示把其他对象进行注入-->
<property name="userDao" ref="UserDao1"></property>
</bean>
<!-- 2创建dao对象 -->
<bean id="UserDao1" class="com.atqijie.spring5.Dao.UserDaoImpl">
</bean>
//部门类
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
}
//员工类
public class Emp {
private String ename;
private String egender;
//员工属于某一个部门 使用对象形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setEgender(String egender) {
this.egender = egender;
}
}
<bean id="emp" class="com.atqijie.spring5.bean.Emp">
<!--设置属性 前两个是基本属性 第三个是对象属性 -->
<property name="ename" value="石晨霖"></property>
<property name="egender" value="女"></property>
<!--对象类型属性 在对象里边嵌套做定义 在一个bean里面嵌套定义另一个bean对象 -->
<property name="dept" >
<bean id="dept" class="com.atqijie.spring5.bean.Dept">
<property name="danme" value="保安部"></property>
</bean>
</property>
</bean>
<!--级联赋值 -->
<bean id="emp" class="com.atqijie.spring5.bean.Emp">
<!--设置属性 前两个是基本属性 第三个是对象属性 -->
<property name="ename" value="石晨霖"></property>
<property name="egender" value="女"></property>
<!--级联赋值 1先在外部bean中注入属性后,再引用-->
<property name="dept" ref="dept"></property>
</bean>
//再外部bean中先注入属性给dept中的普通属性赋值
再在员工类中进行引用 调用外部类的方法是ref 与上述的外部bean注入属性一样
<bean id="dept" class="com.atqijie.spring5.bean.Dept">
<property name="dname" value="财务部"></property>
</bean>
<bean id="emp" class="com.atqijie.spring5.bean.Emp">
<!--设置属性 前两个是基本属性 第三个是对象属性 -->
<property name="ename" value="石晨霖"></property>
<property name="egender" value="女"></property>
<!--级联赋值 1先在外部bean中注入属性后,再引用-->
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="法务部"></property>
</bean>
<bean id="dept" class="com.atqijie.spring5.bean.Dept">
</bean>
private Dept dept;
//生成dept的get方法,必不可少
public Dept getDept(){
return dept;
}
public class Stu {
//数组类型属性
private String[] coursers;
//创建List集合类型属性
private List<String> list;
//Map集合类型属性
private Map<String,String> maps;
//定义set集合类型属性
private Set<String> set;
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void setCoursers(String[] coursers) {
this.coursers = coursers;
}
public void setSet(Set<String> set) {
this.set = set;
}
}
<!--1 集合属性类型属性注入-->
<bean id="stu" class="com.atqijie.spring5.collectiontype.Stu">
<!-- 数组类型的属性注入 value是一个值 但是现在是数组-->
<property name="coursers" >
<!-- 用list 和array都可以-->
<array>
<value>java课程</value>
<value>数据库课程</value>
</array>
</property>
<!-- list集合类型注入-->
<property name="list">
<list>
<value> 张三</value>
<value> 小三</value>
</list>
</property>
<!-- Map类型属性注入 map key value 和之前的list只有value不同-->
<property name="maps">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!-- Set集合类型属性-->
<property name="set">
<set>
<value>mysql</value>
<value>redis</value>
</set>
</property>
</bean>
<!-- 注入的是list集合类型 值是对象的形式 此时是对象类型值 不在是之前的普通string类型 需要用到ref-->
<property name="courselist">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
<!--创建多个course对象-->
<bean id="course1" class="com.atqijie.spring5.collectiontype.Course">
<property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course2" class="com.atqijie.spring5.collectiontype.Course">
<property name="cname" value="Mybatics框架"></property>
</bean>
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/beans/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!--1提取list集合类型注入 -->
<util:list id="booklist" >
<value><![CDATA[三国演义]]></value>
<value><![CDATA[红楼梦]]></value>
<value><![CDATA[水浒传]]></value>
</util:list>
<!-- 提取list集合注入的使用-->
<bean id="book" class="com.atqijie.spring5.collectiontype.Book">
<property name="list" ref="booklist"></property>
</bean>
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<!--P(属性: properties)命名空间 , 直接注入属性-->
<bean id="user" class="com.atqijie.spring5.collectiontype.Monkey" p:name="scl" p:age="18"/>
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<!--C(构造: Constructor)命名空间 , 使用构造器注入-->
<bean id="user" class="com.atqijie.spring5.collectiontype.Monkey" c:name="scl" c:age="18"/>

几种作用域中,request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。
Singleton(单例模式)
当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:
<bean id="monkey" class="com.atqijie.spring5.collectiontype.Monkey" scope="singleton">
<property name="name" value="大雄"/>
</bean>
@Test
public void TestMonkey() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Monkey monkey1 = context.getBean("monkey", Monkey.class);
Monkey monkey2=context.getBean("monkey",Monkey.class);
System.out.println(monkey1);
System.out.println(monkey2);
}

Prototype(原型模式)
我们是否可以创建多个不同的对象?答案当然是可以的
当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将bean定义成prototype,可以这样配置:
<bean id="monkey" class="com.atqijie.spring5.collectiontype.Monkey" scope="prototype">

Request
当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>
针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。
Session
当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。
Bean的自动装配
- 自动装配是使用spring满足bean依赖的一种方法
- spring会在应用上下文中为某个bean寻找其依赖的bean。
- 在xml中显式配置;
- 在java中显式配置;
- 隐式的bean发现机制和自动装配。
Spring的自动装配需要从两个角度来实现,或者说是两个操作:
- 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean;
- 自动装配(autowiring):spring自动满足bean之间的依赖,也就是我们说的IoC/DI;
组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。
推荐不使用自动装配xml配置 , 而使用注解 在实际开发中目前的绝大多数都是使用注解来实现自动装配.
xml的自动配置
!--创建对象-->
<bean id="emp" class="com.atqijie.spring5.collectiontype.autowire.Emp">
<property name="dep" ref="dep"></property>
</bean>
<bean id="dep" class="com.atqijie.spring5.collectiontype.autowire.Dep"></bean>
</beans>
<!--创建对象-->
<!-- 实现自动装配
bean标签中属性 autowire
属性常用两个值
byName根据属性名称注入 注入的id的值 要和类属性名称一样
byType更具属性类型注入
-->
<bean id="emp" class="com.atqijie.spring5.collectiontype.autowire.Emp" autowire="byName">
<!-- <property name="dep" ref="dep"></property>-->
</bean>
<bean id="dep" class="com.atqijie.spring5.collectiontype.autowire.Dep">
</bean>
<bean id="user" class="com.kuang.pojo.User" autowire="byName"> <property name="str" value="qinjiang"/> </bean>
当一个bean节点带有 autowire byName的属性时。
-
将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
-
去spring容器中寻找是否有此字符串名称id的对象。
-
如果有,就取出注入;如果没有,就报空指针异常。
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User" autowire="byType">
<property name="str" value="qinjiang"/>
</bean>
基于注解方式实现对象创建:
准备工作:利用注解的方式注入属性。
1、在spring配置文件中引入context文件头
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
开启属性注解支持
<context:annotation-config/>

<context:component-scan base-package="Service,com.atqijie.spring5.collectiontype"></context:component-scan>
<!--引入名称空间-->
<!-- 开启组件扫描看哪个包哪个类中有注解 此标签是组件扫描 basepackage 是包的名称-->
<!-- 1 扫描多个包使用逗号隔开
2只写扫描包的上层目录
-->
<!-- <context:component-scan base-package="com.atqijie.spring5.collectiontype.Service,com.atqijie.spring5.collectiontype.dao"></context:component-scan>-->
<context:component-scan base-package="com.atqijie"></context:component-scan>
import org.springframework.stereotype.Component;
//使用注解方式创建对象(value属性值可以省略)
//默认值是类名称 首字母小写 UserSservice------userService
@Component(value = "userService")//<bean id="userService" class="...">
public class UserService {
public void add(){
System.out.println("service add..........");
}
!-- <context:component-scan base-package="com.atqijie.spring5.collectiontype.Service,com.atqijie.spring5.collectiontype.dao"></context:component-scan>-->
<context:component-scan base-package="com.atqijie"></context:component-scan>
<!-- use-default-filters="false表示不使用默认filters自己配置filter 过滤器
context:include-filter 扫描那些内容 annotation 根据注解来扫描 只扫描带controller来扫描
-->
<context:component-scan base-package="com.atqijie" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
自动装配注解只能用于带参数的方法:
@Service
public interface PeopleDao {
public void add();
}
@Repository
public class PeopleDaoImpl implements PeopleDao{
@Override
public void add() {
System.out.println("我scl会上不去白银?");
}
}
//被注解的java类当作bean实例
@Service(value ="peopleServiceImpl")
public class PeopleServiceImpl {
// 装配bean
@Autowired//根据类型进行注入
private PeopleDao peopleDao;
public void play() {
System.out.println("我是小夫");
peopleDao.add();
}
}
测试
public class TestService2 {
@Test
public void TestPeopleServiceImpl() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
PeopleServiceImpl peopleServiceImpl = context.getBean("peopleServiceImpl", PeopleServiceImpl.class);
peopleServiceImpl.play();
}
}
结果
@Qualifier
- @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配 根据名称注入
- @Qualifier不能单独使用。
- 一个接口可以有多个实现类 但是如果我们需要一个接口某个特定的实现类,光靠AutoWired根据类的类型注入就不行了。需要具体到某个类名
- 名称可以不写 默认首字母小写
-
//被注解的java类当作bean实例 @Service(value ="peopleServiceImpl") public class PeopleServiceImpl { // 装配bean @Autowired//根据类型进行注入 @Qualifier(value = "SCL") private PeopleDao peopleDao; public void play() { System.out.println("我是小夫"); peopleDao.add(); } }
@Resource
既可以根据类型注入 也可以根据属性注入
- @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
- 其次再进行默认的byName方式进行装配;
- 如果以上都不成功,则按byType的方式自动装配。
- 都不成功,则报异常。
注意Resource 是javax包中的
@Value 注入普通属性
小结
@Autowired与@Resource异同:
1、@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。
2、@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在, 就是只要用于带参数的方法,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用
3、@Resource,默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。
作用域
@scope
- singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
- prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
@Controller("user")
@Scope("prototype")
public class User {
@Value("scl")
public String name;
}
@Configuration//此注解的作用是 让下面的配置类来替代xml配置文件
@ComponentScan(basePackages = {"com.atqijie"})
public class SpringConfig {
}
@Test//涉及到SpringBoot
public void testService2() {
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);//不写默认第一个字母小写 与id一样
System.out.println(userService);
userService.add();
}
本人(学生)也在自学ing,定期写一些博客总结近期的感悟与体会^^
从最基本的开始 加油!
2022年2月20日
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器