springioc+注解

87 阅读5分钟

image.png

 @RequestMapping 设置当前控制器方法请求访问路径
 放在上面表示都有这个路径
 @ConrollerAdvice 
@ExceptionHandler注解我们一般是用来自定义异常的。
可以认为它是一个异常拦截器(处理器)。  
ArithmeticException算数异常
**控制反转**==对象控制权交给别人来完成。降低耦合度
-   依赖注入是控制反转的一种表现方式。
-   依赖查找也是控制反转的一种表现方式
***1为什么每次要new AccountServiceImpl()***
  public class AccountServiceImpl implements AccountService {
    @Override ---重写AccountService里的方法
    public void save(Account account) {
       System.out.println("保存用户信息成功:"+account);
    }
}

public class AccountControllerTest {

    @Test
    public void save() {
        //创建Account对象
        Account account = new Account(1, "特朗普", 5000000.0);
        //创建IOC容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //从容器中获取AccountController对象
        AccountController  accountController = (AccountController) context.getBean("accountController");
        //调用save方法
        accountController.save(account);
    }
}
BeanFactory 才是 Spring 容器中的顶层接口。ApplicationContext 是它的子接口。
 
 

image.png

ApplicationContext接口的实现类

ClassPathXMLApplicationContext 读取类路径下的配置文件(xml)

FileSystemXmlApplicationContext: 读取 绝对路径下的配置文件(一般不用)

AnnotationConfigApplicationContext: 纯注解模式使用创建容器

@Test
public void getBean(){
    //创建IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring02.xml");
    //获取对象:根据id获取对象,返回的是Object对象,需要进行强制转换
    Object obj = context.getBean("account");
    Account account1 = (Account) obj;
    System.out.println(account1);
   ++++++ //获取对象:根据class获取对象,返回Account类型对象,不需要进行强制转换
    
但出现同类型对象会报错
    Account account2  = context.getBean(Account.class);
    System.out.println(account2);
    //获取对象:根据id 和 class 获取对象,返回Account类型对象,不需要进行强制转换
    (需要满足两个条件)
    Account account3  = context.getBean("account", Account.class);
    System.out.println(account3);
     System.out.println(account);
    context1.close();
}
scope 属性可设置值
  singleton[重点]: 单例模式,全局唯一,只会实例化一次, 默认为单例模式
  prototype[重点]: 原型模式(多例模式),每次getBean都会实例化一个新的对象
  request:请求范围
  session:http Session范围
  application:servletContext范围
  websocket: websocket访问(网络套接字)  
  1. 单例模式
	创建容器时创建对象,容器销毁时 对象销毁
2. 原型模式
	创建容器时,对象不会创建,在第一次获取对象时创建对象
	对象不会随着容器的销毁而销毁
3. init-method:指定初始化时执行的方法
4. destory-method:指定销毁时执行的方法,只对scope为singleton的bean有效

依赖注入(DI)

  <bean id="account" class="com.itheima.pojo.Account">
        <property name="id" value="1"></property>
        <property name="name" value="英国女王"></property>
        <property name="money" value="30000000"></property>
    </bean>
1. property标签可以通过set方法给属性赋值
	 name 指定属性名称
	 value  给属性赋的值
2. 本质
	 虽然name指定的属性名,其实本质是调用的是对象的set方法, 如set方法不存在,配置文件会有编译错误
	 注意:set方法一定要符合格式
   需求---- 在开发中,创建其他人定义的对象时,有些属性没有定义set方法,我们也可以采用构造方法注入
   <bean id="account5" class="com.itheima.pojo.Account">
    <property name="birthday" ref="birthday" value"2022-12-9"property>
</bean>
    <constructor-arg name="name"  value="比尔盖茨"></constructor-arg>
通过构造方法给属性赋值
1. 支持按照参数名注入
2. 支持按照类型注入type
3. 支持按照索引注入 index
4. 支持按照顺序注入
    注入引用数据类型:需要先用bean标签创建对象, 再使用ref引用对象
   

注入引用数据类型

需求 如果在Account对象中有一个日期类的属性,应该怎么注入呢?

 有时候我们需要注入一些其他的类型,例如list,set, map ,array 类型的对象
 Account.java 中添加属性
private String[] myStrs;//数组
private List<String> myList;//list集合
private Set<String> mySet;//set集合
private Map<String,String> myMap;//map
private Properties myProps;//Properties
//此处省略set和get方法
//修改toString方法
spring配置文件
<bean id="account7" class="com.itheima.pojo.Account"> 
    <property name="myMap">
        <map>
            <entry key="M" value="Model"></entry>
            <entry key="V" value="View"></entry>
            <entry key="C" value="Controller"></entry>
        </map>
    </property>
    <property name="myProps">
        <props>
            <prop key="M">Model</prop>
            <prop key="V">View</prop>
            <prop key="C">Controller</prop>
        </props>
    </property>
    1. 注入set,list,array 属性,分别使用 set, list , array 标签;
		因为三种标签都是单列数据,可以交换使用,建议按照对应标签配置
2. 注入map,properties 属性,分别使用 map,props 标签	
		因为都是键值对数据,可以交换使用,建议按照对应标签配置
                
</bean>
     +++++  xmlns:context="http://www.springframework.org/schema/context"
 +++++++++   <context:property-placeholder location="classpath:data+.properties"
                                 file-encoding="UTF-8"></contxt:property-placeholder>
  
2. 通过<contxt:property-placeholder> 标签加载属性文件
		location属性指定 属性文件的位置
		属性文件中如果有中文,需要指定加载的编码格式
3. 如果要加载多个属性文件,location属性中提供一个或多个位置作为逗号分隔的列表。
4. 加载类路径下的资源,需要添加字符串前缀:classpath: 
启动注解扫描<context:component-scan base-package="packageName"/>
Bean的定义(@Component)@Component @Controller @Service @Repository
-   位置:类定义上方-   作用:设置该类为spring管理的bean
-   -   @Controller、@Service 、@Repository是@Component的衍生注解,功能同@Component
    -   @Controller 用于Controller层的类 :表现层
    -   @Service 用于Service层的类: 业务层
    -   @Repository 用于Dao层的类: 持久层(一般不写)

-   相关属性

    -   value(默认):定义bean的访问id , 默认的id名称为 "简单类名,首字母小写"
    注入Bean(@Autowired): **@Autowired**、@Qualifier、@Resource
    -   类型:**属性注解**、方法注解(了解即可)
-   位置:可以用在属性上和set方法上, 如果写在属性上,可以没有set方法
-   作用:**自动装配**,设置属性的对象或对方法进行传参(从IOC容器查找对象,赋值 给属性)
-   @Qualifier 可以指定bean的id,一般用于有多个同一类型bean的场景(必须配合@Autowired使用)。
-   @Resource 相当于同时指定了@Autowired和@Qualifier,由Jdk提供的,了解即可。
-   **注解的方式注入bean,不需要setter方法**
-   **注解的方式注入bean,不需要setter方法**

-   相关属性

    -   @Autowired

        -   **required:定义该属性是否允许为null,默认true**

    -   @Qualifier

        -   value:需要注入的bean的id

    -   @Resource不鼓励用

        -   name:需要注入的bean的id
  **@Primary** **类注解**(也可以用于方法上,配合@Bean使用),设置bean的优先级

-   @Autowired默认按类型装配,当出现相同类型的bean,使用@Primary提高按类型自动装配的优先级,程序就不会报错了。
@Primary
@Component
public class ClassName{}
**@Scope** 类注解,设置该类作为bean对应的scope属性

-   相当于`<bean>`标签的`scope`属性
// 默认为singleton
@Scope("prototype")
public class ClassName{}