Java框架-Spring基于注解的IOC配置及纯注解

  • 注解配置与xml配置都实现了减低程序间耦合的功能。
  • 不同公司由不同习惯,有可能是纯xml、纯注解(很少)或者xml与注解混合使用(基于注解的IOC配置)。

1. 基于注解的IOC配置

1.1 创建一个简单案例

1.1.1 创建项目,添加依赖(pom.xml)

<!--导入spring组件包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<!--导入junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>

1.1.2 使用@Component注解创建对象

  • 使用注解创建对象的条件:
    1. 使用@Component对类进行注解;
    2. 开启注解扫描
@Component
public class User {
}

1.1.3 bean.xml配置

1.1.3.1 开启注解扫描(重要)
  • 语法:<context:component-scan base-package="指定扫描的包名"/>
  • 开启后会扫描当前包下所有的类,以及当前包下所有子包下所有的类的注解,会扫描@Component注解及器衍生注解@Controller @Service @Repository
<?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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--开启注解扫描-->
    <!--
        base-package
        1. 指定扫描的包名称
        2. 会扫描当前包下所有的类,以及当前包下所有子包下所有的类
        3. 如果要扫描多个包,用逗号隔开
    -->
    <context:component-scan base-package="com.azure.entity"/>

</beans>

1.1.4 测试类

public class annoTest {
    @Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        User user = (User) ac.getBean("user");
        System.out.println(user);
    }
}

2. 常用注解

2.1 创建对象注解

2.1.1 @Component

  • 作用:把对象交给 spring的ioc容器来管理。相当于在 xml 中配置一个 bean标签
  • 属性:value:指定对象的名称,相当于bean标签的id。**如果不指定 value 属性,默认对象名称为当前类的类名,且首字母小写。**如@Component(value=“user”),属性值只有一个时,可以省略成@Component(“user”)

2.1.2 @Controller @Service @Repository

  • @Component的衍生注解,其作用及属性与@Component一致

  • 作用范围不同:

    @Controller: 一般用于表现层的注解。
    @Service: 一般用于业务层的注解。
    @Repository: 一般用于持久层的注解。
    @Component: 除了上述三层架构的其余注解,如工具类等。

  • 如果注解中有且只有一个属性要赋值时,且名称是 value, value 在赋值是可以不写。

2.2 依赖注入注解

2.2.1 @Autowired(重点)

  • 作用:自动按照类型注入依赖,相当于使用set方法注入。
  • 属性:required(一般很少会设置)
    • true:默认值,标识必须从容器中找到对应的对象注入,否则报错;
    • false:如果去容器中没有找到对应的对象注入不会报错。
  • 注意事项:只能注入bean类型
2.2.1.1 定义到字段

查找顺序:

  1. 先根据字段的类型,寻找容器中该类型对应的对象注入;
  2. 如果该类型的对象有多个
    • 再根据字段的名称查找容器中的对象,成功找到就注入;
    • 如果根据名称找不到对应对象,则报错。
2.2.1.2 定义到方法

查找顺序:

  1. 先根据参数的类型,寻找容器中该类型对应的对象注入;
  2. 如果该类型的对象有多个
    • 再根据参数的名称查找容器中的对象,成功找到就注入;
    • 如果根据名称找不到对应对象,则报错。
2.2.1.3 演示示例
  1. bean.xml配置

    <!--创建String类型对象并放入ioc容器中-->
    <bean id="str" class="java.lang.String">
        <constructor-arg value="JoJo"></constructor-arg>
    </bean>
    <bean id="name" class="java.lang.String">
        <constructor-arg value="Dio哒"></constructor-arg>
    </bean>
    
  2. 定义到字段

    @Component("user")
    public class User {
    
        /**
         * @Autowired
         * 1.先根据修饰的字段的类型,去容器中找该类型对应的对象注入;
         * 2.如果该类型的对象有多个,
         *   a.会根据字段的名称去容器中找对象注入,找到就成功注入;
         *   b.根据字段的名称去容器中没有找到对应的对象,就报错。
         * 3.细节
         *   @Autowired注解的属性required
         *   true 默认值,标识必须从容器中找到对应的对象注入否则报错。
         *   false 如果去容器中没有找到对应的对象注入不会报错
         */
        @Autowired
        private String name;
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    由于ioc容器中有多个String类型的对象,所以会根据字段名“name”查找,如果只有一个String类型的对象,则会把该对象注入

  3. 定义到方法

    /**
     * @Autowired 定义在方法上
     * 1.先根据参数类型去容器找对象注入
     * 2.如果类型有多个,会根据参数名称去容器中找对象注入;根据名称也没有找到就报错。
     */
    @Autowired
    public void setName(String name) {
        System.out.println(name);
    }
    

    同样,由于ioc容器中有多个String类型的对象,所以会根据字段名“name”查找,如果只有一个String类型的对象,则会把该对象注入

2.2.2 @Qualifier

  • 作用:在自动按照类型注入依赖的基础上,在按照Bean的id注入。
  • 属性:value:用于指定bean的id
  • 注意事项:给字段注入时不能独立使用,必须和@Autowire 一起使用;只有给方法参数注入时,才可以独立使用(纯注解时使用)
/**
 * @Qualifier("str")
 * 1.表示根据str这个名称,去容器中找对象注入
 * 2.@Qualifier通常都要与@Autowired一起使用
 *   只要@Qualifier修饰方法参数时候才可以单独使用(纯注解时候使用)
 * 3.根据@Autowired的特性,注入的应该是名为name的String类型对象,而使用@Qualifier
 *   则会将str对象注入
 */
@Autowired
@Qualifier("str")
private String nickname;

2.2.3 @Resource

  • 作用:按照 bean 的 id 注入或者类型注入。

  • 属性:name:指定 bean 的 id(名称),name不能省略

    type:指定bean的类型

  • 查找顺序:

    1. 根据字段的名称,在容器中找对应名称对象注入;
    2. 如果该类型的对象有多个
      • 再根据参数的名称查找容器中的对象,成功找到就注入;
      • 如果根据名称找不到对应对象,则报错。
  • 注意事项:只能注入bean类型;jdk9及之后版本不再支持此注解

/**
 * @Resource
 * 1.根据字段名称去容器中找对象注入
 * 2.如果根据名称会根据类型找,如果类型有多个就报错
 * 3.也可以通过注解的name属性指定只根据名称找
 *   如果指定type只会根据类型找。
 * 不推荐使用。因为jdk8以后的版本不支持此注解。
 */
@Resource(name = "str")
private String oldName;

2.2.4 @Value

  • 作用:给基本数据类型和String类型的字段注入值;获取加载的 properties配置文件的值(纯注解中使用)
  • 属性:value:被注入的值
/**
 * @Value
 * 1.给简单类型的字段赋值
 * 2.获取加载的properties配置文件的值(纯注解中讲解)
 */
@Value("100")
private int id;
@Value("女")
private String sex;

2.3 改变作用范围注解

2.3.1 @Scope

  • 作用:指定 bean 的作用范围。类似于bean标签的scope属性

  • 属性:value:指定范围的值。

    取值:

    • singleton:单例,默认值
    • prototype:多例
    • request:创建的对象的范围与request域一样。web项目
    • session:创建的对象的范围与session域一样。web项目
    • global session:全局session。分布式系统中使用。web项目
/*@Scope注解*/
@Component("user")
//@Scope("singleton")// 单例,默认值
@Scope("prototype")// 多例
public class User {
	//...
}

2.4 与生命周期相关的注解

2.4.1 @PostConstruct

  • 作用:指定初始化方法。相当于bean标签中的init-method属性

2.4.2 @PreDestroy

  • 作用:指定容器销毁方法。相当于bean标签中的destroy-method属性

2.4.3 @Lazy

  • 作用:延迟初始化。在第一次从容器中获取对象时才会创建对象。相当于bean标签中的lazy-init属性
  • 注意事项:只对单例有效

2.4.4 生命周期注解示例

/*生命周期注解*/
@Component("user2")
@Scope("singleton")
@Lazy  // 延迟初始化,再第一次从容器中获取对象时候才创建对象。只对单例有效
public class User2 {
    
    // 创建对象之后执行
    @PostConstruct
    public void init() {
        System.out.println("创建对象之后执行");
    }

    // 销毁容器之前执行
    @PreDestroy
    public void preDestroy() {
        System.out.println("销毁容器之前执行");
    }
}

2.5 Spring中注解与xml方式的选择

  • 注解的优势:

    配置简单,维护方便(找到类相当于找到对应的配置)。

  • XML 的优势:

    修改时,不用改源码。不涉及重新编译和部署。

Spring 管理 Bean,XML与注解方式的比较:

在这里插入图片描述

小结

  • 基于注解的 spring IoC 配置中, bean 对象的特点和基于 XML 配置是一致的。
  • xml 配置 可以与注解配置一起使用。

目前开发比较常用的是:

  • XML + 注解 混合使用
    • XML: 配置一些全局的对象(举例:DataSource/JdbcTemplate…)
    • 注解: 每一个模块的dao/service等对象的创建可以用注解,简化配置

3. 使用注解 IOC 改造三层架构案例

  • 需求:使用xml+注解的形式改造纯xml配置的三层架构案例

3.1 环境搭建和实体类

  • 不用修改
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.azure</groupId>
    <artifactId>day52projects_spring_xml</artifactId>
    <version>1.0-SNAPSHOT</version>
<dependencies>
    <!--导入spring组件包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <!--导入druid-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!--导入mysql驱动包-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.32</version>
    </dependency>
    <!--导入junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>  
</project>

实体类

public class account {
    private int accountId;
    private int uid;
    private double money;
    /*省略无参、有参、toString、getter&setter*/
}

3.3 dao层

3.3.1 dao接口

  • 不用修改
public interface IAccountDao {
    //添加
    void save(Account account);
    //更新
    void update(Account account);
    //删除
    void delete(int id);
    //查询
    List<Account> findAll();
}

3.3.2 dao实现类

/*标识持久层,加入ioc容器中*/
@Repository
public class AccountDaoImpl implements IAccountDao {

    //从容器中获取JdbcTemplate对象并自动注入
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void save(Account account) {
        jdbcTemplate.update("insert into account values (null,?,?)",account.getUid(),account.getMoney());
    }
    @Override
    public void update(Account account) {
        jdbcTemplate.update("update account set  uid=?,money=? where accountId=?",account.getUid(),account.getMoney(),account.getAccountId());
    }
    @Override
    public void delete(int id) {
        jdbcTemplate.update("delete from account where accountId=?",id);
    }
    @Override
    public List<Account> findAll() {
        return jdbcTemplate.query("select * from account",new BeanPropertyRowMapper<>(Account.class));
    }
}

3.4 service层

3.4.1 service接口

  • 不用修改
public interface IAccountService {
    //添加
    void save(Account account);
    //更新
    void update(Account account);
    //删除
    void delete(int id);
    //查询
    List<Account> findAll();
}

3.4.2 service实现类

/*标识业务层,加入ioc容器中*/
@Service
public class AccountServiceImpl implements IAccountService {

    //从容器中获取dao对象并自动注入
    @Autowired
    private IAccountDao accountDao;

    @Override
    public void save(Account account) {
        accountDao.save(account);
    }
    @Override
    public void update(Account account) {
        accountDao.update(account);
    }
    @Override
    public void delete(int id) {
        accountDao.delete(id);
    }
    @Override
    public List<Account> findAll() {
        return accountDao.findAll();
    }
}

3.5 bean_IOC.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: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.xsd">

     <!--开启注解扫描-->   
    <context:component-scan base-package="com.azure"/>
    <!--加载jdbc.properties配置文件-->
    <!--注意整个语句的写法-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--1.创建连接池对象-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--使用${key}根据指定key在properties文件中获取对应的值}-->
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    <!--2.创建jdbcTemplate对象,注入连接池对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

3.6 测试类

  • 重点:改造后,service对象由ioc容器中获取。根据@Service标签的特性,由于设置标签时没有指定对象名称(即value属性值),所以按照默认对象名称(即当前类的类名,且首字母小写)!!所以getBean方法传入的对象名称是accountServiceImpl而不是accountService
public class WebApp {

    /*测试类中创建容器获取service对象*/
    private ApplicationContext ac = new ClassPathXmlApplicationContext("bean_IOC.xml");
    private IAccountService accountService = (IAccountService) ac.getBean("accountServiceImpl");
    
    @Test
    public void save() {
        Account account = new Account();
        account.setUid(46);
        account.setMoney(99D);
        accountService.save(account);
    }
    @Test
    public void update() {
        Account account = new Account();
        account.setAccountId(1);
        account.setUid(46);
        account.setMoney(99D);
        accountService.update(account);
    }
    @Test
    public void delete() {
        accountService.delete(4);
    }
    @Test
    public void findAll() {
        System.out.println(accountService.findAll());
    }
}

4. spring 的纯注解配置

  • 将bean.xml的所有配置都用注解实现
  • 使用纯注解比较少见,因为如果要修改部分功能,可能会修改源码,反而会增加耦合性。
  • 根据企业要求或者简化开发的原则来选择配置原则,不一定非要纯注解

4.1 纯注解配置所需的新注解

4.1.1 @Configuration

  • 作用:用于指定当前类是一个 spring 配置类, 当创建容器时会从该类上加载注解,用于取代bean.xml。
  • 属性:value:用于指定配置类的字节码
  • 注意事项:获取容器时需要使用AnnotationApplicationContext类,才可以加载@Configuration注解的类的字节码对象。
/**
 * @Configuration
 * 1.注解修饰的类就是配置管理类,相当于bean.xml配置
 * 2.现在创建容器时候,只需要加载此注解修饰的类即可。
 */
@Configuration
public class SpringConfiguration {
}

4.1.2 @ComponentScan

  • 作用:用于指定 spring 在初始化容器时要扫描的包。 作用和在 spring 的 xml 配置文件中的:<context:component-scan base-package="指定扫描的包名"/>一致。
  • 属性:basePackages:用于指定要扫描的包。与该注解中的 value 属性作用一致。
/**
 * @Configuration
 * 1.注解修饰的类就是配置管理类,相当于bean.xml配置
 * 2.现在创建容器时候,只需要加载此注解修饰的类即可。
 * 
 * @ComponentScan
 * 开启注解扫描,指定要扫描的包
 * 可以写成@ComponentScan("com.azure")/@ComponentScan(value = "com.azure")/@ComponentScan(basePackages = "com.azure")
 */
@Configuration
@ComponentScan(value = "com.azure")
public class SpringConfiguration {
}

4.1.3 @Bean和@PropertySource

4.1.3.1 @Bean
  • 作用:该注解只能写在方法上,@Bean 会自动把方法返回的结果加入ioc容器。同时将容器中的对象注入到方法参数中。

  • 属性:name:给当前@Bean 注解方法创建的对象指定一个名称(即相当于bean 标签的 id)。

  • @Bean 修饰的方法的参数:

    1. 自动根据参数类型去容器中对象注入;
    2. 如果类型有多个,就根据形参名称取容器找该名称对应的对象注入
    3. 如果要根据指定名称在容器中找对象注入参数,需要用@Qualifier注解
4.1.3.2 @PropertySource
  • 作用:用于加载.properties 文件中的配置。
  • 属性:value[]:用于指定 properties 文件位置。
  • 注意事项:属性value[]中的文件位置是在类路径下,需要写上classpath
4.1.3.3 使用新的类加载数据库连接池、jdbcTemplate
@PropertySource("jdbc.properties")
public class JdbcConfig {
    // 通过@Value获取配置文件值
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 1.创建连接池,加入ioc容器
     * @Bean 会自动把方法返回的结果加入ioc容器
     *       name属性指定加入ioc容器的对象的名称
     */
    @Bean(name = "dataSource")
    public DataSource createDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }

    /**
     * 2.创建JdbcTemplate,加入ioc容器
     * @Bean 修饰的方法的参数:
     * 1.会自动根据参数类型去容器中对象注入;
     * 2.如果类型有多个,就根据形参名称取容器找该名称对应的对象注入。
     */

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
}

4.1.4 @Import

  • 作用:用于导入其他配置类,也就是建立各配置类与主配置类的关系。

  • 属性:value[]:用于指定其他配置类的字节码对象。

  • 注意事项:在引入其他配置类时,可以不用再写@Configuration 注解,也可以写

/**
 * @Configuration
 * 1.注解修饰的类就是配置管理类,相当于bean.xml配置
 * 2.现在创建容器时候,只需要加载此注解修饰的类即可。
 *
 * @ComponentScan
 * 开启注解扫描,指定要扫描的包
 * 可以写成@ComponentScan("com.azure")/@ComponentScan(value = "com.azure")/@ComponentScan(basePackages = "com.azure")
 *
 * @Import
 * 用来导入其他的配置类
 */
@Configuration
@ComponentScan(value = "com.azure")
@Import(JdbcConfig.class)
public class SpringConfiguration {
}

4.2 测试类

public class annoTest {
    @Test
    public void test(){
        //使用注解方式创建容器
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        // 从容器中获取对象
        IAccountService accountService = (IAccountService) ac.getBean("accountServiceImpl");
        System.out.println(accountService.findAll());
    }
}

4.3 使用@Qualifier注解指定@Bean参数名称

   /**
     * 1.创建连接池,加入ioc容器
     * @Bean 会自动把方法返回的结果加入ioc容器
     *       name属性指定加入ioc容器的对象的名称
     */
    @Bean(name = "dataSource1")
    public DataSource createDataSource1(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }

    @Bean(name = "dataSource2")
    public DataSource createDataSource2(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }

    /**
     * 2.创建JdbcTemplate,加入ioc容器
     * @Bean 修饰的方法的参数:
     * 1.会自动根据参数类型去容器中对象注入;
     * 2.如果类型有多个,就根据形参名称取容器找该名称对应的对象注入。
     * 3.如果想根据指定的名称去容器中找对象,注入到方法的形参上,使用@Qualifier注解
     *   @Qualifier("dataSource2") 去容器找名称是“dataSource2”的对象注入方法形参。
     */

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(@Qualifier("dataSource2") DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
}

5. Spring整合Junit

  • 利用Spring框架提供的运行器,根据配置文件或注解来在Junit代码中的获取ioc容器

5.1添加spring-test依赖

1540300218778

5.2 测试类

5.2.1 纯注解方式

/*spring对Junit的支持*/
@RunWith(SpringJUnit4ClassRunner.class)
//指定容器类
@ContextConfiguration(classes = SpringConfiguration.class)
public class Test01 {
    // 注入service(因为运行junit容器已经初始化,标识运行的测试类在容器范围内,所有可以直接注入。)
    @Autowired
    private IAccountService accountService;

    @Test
    public void findAll() {
        System.out.println(accountService.findAll());
    }
}

5.2.2 加载bean.xml配置文件

/*spring对Junit的支持*/
@RunWith(SpringJUnit4ClassRunner.class)
//指定容器类
@ContextConfiguration(locations = "classpath:bean_test.xml")
public class Test02 {
    // 注入service(因为运行junit容器已经初始化,标识运行的测试类在容器范围内,所有可以直接注入。)
    @Autowired
    private IAccountService accountService;

    @Test
    public void findAll() {
        System.out.println(accountService.findAll());
    }
}

6. 总结

  1. JdbcTemplate实现crud,SpringIOC容器创建对象,依赖注入, XML方式

  2. 常用的注解

    • @Component 创建对象加入容器, 例如:工具类、其他组件

    • @Repository 创建对象加入容器, 例如:标识数据库访问层的组件

    • @Service 创建对象加入容器, 例如:标识乐屋逻辑层的组件

    • @Controller 创建对象加入容器 例如:标识控制层的组件

    • @Autowired 从容器中找对象,给属性赋值。根据类型、名称去容器中找。

    • @Qualifier 结合Autowired使用,可以指定按照名称去容器找对象注入。

    • @Value 给简单类型属性直接赋值/获取配置文件值@Value(“${key}”)

    • @Resource 从容器中找对象,给属性赋值。 根据名称、类型去容器中查找

    • @Scope 单例/多例

    • @PostConstruct 初始化方法,创建对象后执行

    • @PreDestroy 销毁先执行

    • @Lazy 延迟初始化

  3. 优化案例

  4. 零配置使用的注解、案例优化

    • @Configuration 取代bean.xml ;
    • @ComponentScan 注解扫描
    • @Import 导入其他配置类
    • @Bean 修饰方法,自动把方法返回值放入容器
    • @PropertySource 加载外部配置文件
    • @Value 获取@ PropertySource加载的配置文件的值

猜你喜欢

转载自blog.csdn.net/KeepStruggling/article/details/83450010