04-Spring-注解的IOC和DI

2020-12-30  本文已影响0人  XAbo

**Spring总结:1.通过IOC容器管理Bean。 2.通过DI管理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: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/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--告知Spring Bean的创建配置在类中  新增context命名空间   -->
  <context:component-scan base-package="com.annotation"></context:component-scan>

</beans>

AccountServicesImpl:

/*  
 XML的配置
<bean id="accountServices" class="com.annotation.services.AccountServicesImpl" scope="" init-method="" destory-method="">
    <property name="" value=""></property>
    <property name="" ref=""> </property>
</bean>
--1 xml实现的功能:

 1.用于管理对象:1.1 bean标签创建对象; 1.2 init-method destory-method;管理bean的生命周期 ; 1.3 scope:管理bean的作用范围。
 2.用于注入数据:property。

--2 注解实现的功能:

 1.用于管理对象:
     1.1 @Component创建对象,将当前对象存入IOC容器 ,其属性value用于指定bean的id,默认是当前类名(首字母小写)。
     1.2 @Controller:表现层  @Service:业务/服务层  @Repository:持久层 这三个注解的作用和属性跟@Component一样。
 2.用于注入数据的(JavaBean类型)
    2.1 @Autowired:按照类型注入,Bean对象类型和要注入的变量类型匹配。
       2.1.1 注入不依赖构造方法或set方法,Spring直接在IOC容器中找到“合适”的一个对象,将其属性注入。
       2.1.2 当IOC容器中有多个匹配到的话,在根据变量名称进行匹配。
    2.2 @Qualifier:按照类型基础之上再按照名称注入,value属性指定Bean的ID。
      2.2.1 给类成员注入时不能单独使用,需要跟Autowired配合使用。
      2.2.2 给方法参数注入时可以。
    2.3 @Resource:直接按照Bean的id注入,可独立使用。使用name来指定Bean的id。
 3. 用于注入数据的(基本和String类型)
    3.1 @Value:使用value属性指定要注入的值,可使用spEL。${表达式}
 4. 用于注入数据的:集合类型的属性只能通过XML进行注入。
 5. 管理Bean的作用范围:@Scope指定bean的作用范围,属性value指定范围的取值。
 6. 管理Bean的生命周期:@PreDestory :用于指定销毁方法。 @PostConstruct :用于指定初始化方法。

 补充:@Autowired注解位置:
   1.放置在对应成员变量的set方法上.[弱依赖,可有可无,不影响整个类]
   2.放置在成员变量上,Spring通过反射直接对成员变量进行注入(推荐)[有缺点,idea还会警告:不建议使用这种方式注入]
   3.放在构造器上[强制依赖]
 */
@Component(value = "accountServices")
public class AccountServicesImpl implements AccountServices {

     //@Autowired
     @Resource
    private AccountDao accountDao;

    public void saveAccount() {
         accountDao.saveAccount();
    }
}

注解的Autowired方式

AccountDaoImpl:

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
    @Override
    public void saveAccount() {
        System.out.println("DAO---保存账户数据");
    }
}

客户端:

public class client {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext  ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
        AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
        accountServices.saveAccount();
    }
}

二、依赖第三方jar

1.当依赖第三方jar包的时候,不能使用注解的时候,如何去掉剩余标签?

<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
       2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
  -->

<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
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--告知Spring Bean的创建配置在类中  新增context命名空间   -->
  <context:component-scan base-package="com.annotation"></context:component-scan>
 <!--这些bean不能使用注解写在源码上-->
 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSourrce">
     <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
     <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb"></property>
     <property name="user" value="root"></property>
     <property name="password"  value="213"></property>
 </bean>
 <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
    <constructor-arg name="ds" ref="dataSource"></constructor-arg>
 </bean>

</beans>

2.使用新注解解决bean配置文件中遗留的便签。
使用SpringConfig类:

/*
* @Configuration:指定当前类是一个配置类.
* @ComponentScan:通过注解指定spring在创建容器时候要扫码的包。等同于:<context:component-scan base-package="com.annotation"></context:component-scan>
* @Bean:把当前方法的返回值放入SpringIOC容器中。属性:name指定bean的id,默认是当前方法名。其装配bean的方式与@Autowired相似。
  @PropertySource指定加载的properties配置文件。classpath表示类路径。
* */
@Configuration
@ComponentScan(basePackages = "com.annotation")
//@Import("otherConfig.class")  可导入其他配置子类。 
/*@Import相当于xml文件中的
 * <import resource="classpath*:/spring/job-timer.xml" />
 */
@PropertySource("classpath:db.properties")
public class SpringConfig {
 @Valure("$jdbc.driver")
 private String driver;
 @Valure("$jdbc.url")
 private String url;
 @Valure("$jdbc.user")
 private String user;
 @Valure("$jdbc.pwd")
 private String passWrod ;

@Bean(name="dataSource")
public DataSource createDataSource(){
    ComboPooledDataSourrce ds = new ComboPooledDataSourrce()
    //ds.setDriverClass("com.mysql.jdbc.Driver");
    //ds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
    //ds.setUser("root");
    //ds.setPassword("123");
    ds.setDriverClass(driver);
    ds.setJdbcUrl(url);
    ds.setUser(user);
    ds.setPassword(passWrod);
    return ds;
}
@Bean(name="runner")
@Scope("prototype")
public QueryRunner createQueryRunner(DataSource dataSource){
    return  new QueryRunner(dataSource);
}
}

用到的db.properties配置文件

#mysql jdbc
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.user=root
jdbc.pwd=123

3.此时不需要bean配置文件。

三、集成junit

1.传统的测试用例

import com.annotation.services.AccountServices;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AccountServiceTest {
    @Test
    public void testFindAll() {
        ClassPathXmlApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
        AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
        List<Account> accounts = accountServices.findAll();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

    @Test
    public void testFindOne() {
        ClassPathXmlApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
        AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
        Account accounts = accountServices.findOne("xzb");
        System.out.println(account);

    }
}

2.Spring集成junit

import com.annotation.services.AccountServices;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/*
* Spring整合junit
* 1.导入spring整合junit的jar
* 2.@RunWith,使用junit提供一个注解把原有的main方法替代了,换成spring提供的。
* 3.@ContextConfiguration 告知spring的运行器,spring的IOC容器创建是xml还是注解。Spring 5.x <---> junit 4.12+
*   location:指定XML文件的位置,加上classpath,表示在类路径下。
*   classes:指定注解所在位置。
*/

@RunWith(SpringJUnit4ClassRunner.class)//指定main
@ContextConfiguration(SpringConfig.class)//获取Sping IOC容器
//@ContextConfiguration(locations= {"classpath:bean.xml"})
public class AccountServiceTest {
    @Autowired
    private AccountServices accountServices  = null;
    @Test
    public void testFindAll() {
        List<Account> accounts = accountServices.findAll();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

    @Test
    public void testFindOne() {
        Account accounts = accountServices.findOne("xzb");
        System.out.println(account);

    }
}

junit为什么不采用配置到 xml 中的方式呢?
第一:当我们在 xml 中配置了一个 bean, spring 加载配置文件创建容器时,就会创建对象。
第二:测试类只是我们在测试功能时使用,而在项目中它并不参与程序逻辑,也不会解决需求上的问
题,所以创建完了,并没有使用。那么存在容器中就会造成资源的浪费。

上一篇下一篇

猜你喜欢

热点阅读