70-AOP面向切面编程和DI依赖注入DI

63 阅读5分钟
配置文件中Bean标签 和注解的形式替代xml配置 这两种配置方式 都要掌握
-   在上面的案例中,成功做到了把AccountService对象赋值给了AccountController的属性;它们之间的关系是由spring配置实现的;
-   这种优化方案其实就是依赖注入。
-   依赖注入是控制反转的一种表现方式。
 依赖查找也是控制反转的一种表现方式
 id: 唯一的标识    class: 类的全限定名称,如果没有空的构造方法,需要其他的配置
 2.  配置文件spring02.xml
 <bean id="account" class="com.itheima.pojo.Account"  init-method="init"
            destroy-method="destroy"  scope="singleton/prototype"></bean>
     <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>           
scope 属性可设置值
  singleton[重点]: 单例模式,全局唯一,只会实例化一次, 默认为单例模式
  prototype[重点]: 原型模式(多例模式),每次getBean都会实例化一个新的对象
  request:请求范围
  session:http Session范围
  application:servletContext范围
  websocket: websocket访问(网络套接字)  
1. 单例模式 	创建容器时创建对象,容器销毁时 对象销毁
2. 原型模式
	创建容器时,对象不会创建,在第一次获取对象时创建对象
	对象不会随着容器的销毁而销毁
3. init-method:指定初始化时执行的方法
4. destory-method:指定销毁时执行的方法,只对scope为singleton的bean有效
BeanFactory 才是 Spring 容器中的顶层接口。  
ApplicationContext 是操作容器接口,是BeanFactory 的子接口。
 创建和获取对象 	剖析获取spring容器对象的方法
1. 根据id获取对象,返回的是Object对象,需要进行强制转换
   context.getBean("account"); 
2. 根据class获取对象,返回Account类型对象,不需要进行强制转换
    context.getBean(Account.class); 
3. 根据id 和 class获取对象,返回Account类型对象,不需要进行强制转换(需要满足两个条件)
    context.getBean("account", Account.class);    
@Test
public void getBean(){
    //创建IOC容器
    //ClassPathXMLApplicationContext  读取类路径下的配置文件(xml)
    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);
    context.close();//查询创建销毁时机才写
}
总结1. 注入set,list,array 属性,分别使用 set, list , array 标签;
		因为三种标签都是单列数据,可以交换使用,建议按照对应标签配置
2. 注入map,properties 属性,分别使用 map,props 标签	
		因为都是键值对数据,可以交换使用,建议按照对应标签配置
1. <contxt:property-placeholder> 需要新增名称空间,具体看下图
2. 通过<contxt:property-placeholder> 标签加载属性文件
		location属性指定 属性文件的位置
		属性文件中如果有中文,需要指定加载的编码格式
3. 如果要加载多个属性文件,location属性中提供一个或多个位置作为逗号分隔的列表。
4. 加载类路径下的资源,需要添加字符串前缀:classpath: 
通过set方法给account的属性赋值
1. property标签可以通过set方法给属性赋值
	 name 指定属性名称  value  给属性赋的值
 如set方法不存在,配置文件会有编译错误 set方法一定要符合格式
 创建其他人定义的对象时,有些属性没有定义set方法,我们也可以采用构造方法注入  

通过构造方法给属性赋值
        <constructor-arg index索引="0" type类型="java.lang.Integer" name="money" value参数名="比尔盖茨"></constructor-arg>
注入引用数据类型,总结注入引用数据类型:需要先用bean标签创建对象, 再使用ref引用对象 
1日期类并添加set和get方法,修改toString方法
private Date birthday;
spring配置文件
<bean id="birthday" class="java.util.Date"></bean>
<bean id="account5" class="com.itheima.pojo.Account">
    <property name="birthday" ref="birthday"></property>
</bean>
2注入 list,set, map ,array 类型的对象
spring配置文件
<bean id="account7" class="com.itheima.pojo.Account">
    <property name="myStrs">
        <array>
            <value>mybatis</value>
            <value>spring</value>
            <value>springMVC</value>
        </array>
    </property>
    <property name="myList">
        <list>
            <value>表现层</value>
            <value>业务层</value>
            <value>持久层</value>
        </list>
    </property>
    <property name="mySet">
        <set>
            <value>模型层</value>
            <value>视图层</value>
            <value>控制层</value>
        </set>
    </property>
    <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>
</bean>
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方法
代码 data.properties
account.id=1
account.name=zhangsan
account.money=3000000
<?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:contxt="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 
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:data.properties"
                                 file-encoding="UTF-8"></contxt:property-placeholder>
    <bean id="account9" class="com.itheima.pojo.Account">
        <property name="id" value="${account.id}"></property>
        <property name="name" value="${account.name}"></property>
        <property name="money" value="${account.money}"></property>
    </bean>
</beans>
注入Bean(@Autowired)启动注解扫描,加载类中配置的注解项<context:component-scan base-package="packageName"/>
Bean的定义(@Component设置该类为spring管理的bean)
1@Component @Controller @Service @Repository
- @Controller、@Service 、@Repository是@Component的衍生注解,功能同@Component
- @Controller   用于Controller层的类 :表现层
- @Service        用于Service层的类: 业务层
- @Repository  用于Dao层的类: 持久层(一般不写)
- 相关属性 value(默认):定义bean的访问id ,   默认的id名称为 "简单类名,首字母小写"
2注入Bean@Autowired @Autowired、@Qualifier、@Resource
可以用在属性上和set方法上, 如果写在属性上,可以没有set方法

自动装配,设置属性的对象或对方法进行传参(从IOC容器查找对象,赋值 给属性)
@Autowired  按类型装配,一般生产中都使用它,由spring提供的,只有引入spring包才可使用。
@Qualifier     可以指定bean的id,一般用于有多个同一类型bean的场景(必须配合@Autowired使用)。
@Resource=@Autowired +@Qualifier
注解的方式注入bean,不需要setter方法
@Autowiredrequired:定义该属性是否允许为null,默认true
Qualifier value:需要注入的bean的id
@Primary 类注解设置bean的优先级,也可以用于方法上,配合@Bean使用
@Autowired默认按类型装配,当出现相同类型的bean,使用@Primary提高按类型自动装配的优先级,程序就不会报错了。
@Primary
@Component
public class ClassName{}
@Scope 类注解,相当于<bean>标签的scope属性
// 默认为singleton
@Scope("prototype")
public class ClassName{}    

```-