Bootstrap

Spring2(bean实例化的管理 bean的作用域 spring对于bean的生命周期管理 annotation注解 javaconfig 实现单表增删改查(spring)面试题 )

目录

一、spring对于bean实例化的管理

1.默认情况下调用类的无参构造方法进行

2.通过普通工厂进行对象的实例化

3.通过静态工厂进行对象的实例化

二、spring对于bean的作用域

三、spring对于bean的生命周期管理

四、annotation注解

1. 注入类 

 2. 注入基本数据,javaBean

3.其他注解

实现

五、javaconfig 

实现 

六、实现单表增删改查 (spring)

1. xml实现

2. annotation注解

3. javaconfig

七、面试题

6. 什么是Spring 的bean

7. 将一个类声明为Bean的注解有哪些?

8. @Component和@Bean的区别是什么?

9. @Autowired和@Resource的区别是什么? 

10. Spring框架中的常见注入方式有几种?  

11. Spring中常见的ApplicationContext实现类有哪些?

12. BeanFactory和ApplicationContext有什么区别? 

13. Spring 框架启动流程(了解) 

14. Spring 框架中的Bean的作用域 

15. Spring 框架中的Bean的线程安全


一、spring对于bean实例化的管理

======================springIOC/DI=========================

 spring==bean容器===bean的管理

 配置略

1.默认情况下调用类的无参构造方法进行

beans.xml

  <!-- =========================bean的实例化方式1============================== -->
    <bean id="student" class="com.zkt.pojo.Student"></bean>

pojo Student

public class Student {
    private String stuName;
    private String stuHobby;
    private int stuAge;

    @Override
    public String toString() {
        return "Student{" +
                "stuName='" + stuName + '\'' +
                ", stuHobby='" + stuHobby + '\'' +
                ", stuAge=" + stuAge +
                '}';
    }

    public Student() {
        System.out.println("===》执行studnet的无参构造方法");
    }
}

测试

public class Test01 {
    public static void main(String[] args) {
        //1.加载spring主配置文件,获取spring核心对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

        Student student1 = (Student) applicationContext.getBean("student");
        Student student2 = (Student) applicationContext.getBean("student");
        System.out.println(student1 == student2);
    }
}

2.通过普通工厂进行对象的实例化

beans.xml

 <!-- =========================bean的实例化方式2============================== -->
    <bean id="student" class="com.zkt.pojo.Student" factory-bean="factory" factory-method="createStu"></bean>
    <bean id="factory" class="com.zkt.factory.BeansFactory"></bean>

factory BeansFactory

public class BeansFactory {
    public Student createStu(){
        System.out.println("===》执行工厂方法");
        return new Student();
    }
}

测试

public class Test01 {
    public static void main(String[] args) {
        //1.加载spring主配置文件,获取spring核心对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

        Student student1 = (Student) applicationContext.getBean("student");
        Student student2 = (Student) applicationContext.getBean("student");
        System.out.println(student1 == student2);
    }
}

3.通过静态工厂进行对象的实例化

beans.xml

<!-- =========================bean的实例化方式3============================== -->
    <bean id="student" class="com.zkt.factory.StaticBeansFactory" factory-method="createStu"></bean>

factory StaticBeansFactory

public class StaticBeansFactory {
    public static Student createStu(){
        System.out.println("===》执行static工厂方法");
        return new Student();
    }
}

测试

public class Test01 {
    public static void main(String[] args) {
        //1.加载spring主配置文件,获取spring核心对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

        Student student1 = (Student) applicationContext.getBean("student");
        Student student2 = (Student) applicationContext.getBean("student");
        System.out.println(student1 == student2);
    }
}

二、spring对于bean的作用域

含义:bean在spring容器中创建的策略以及访问的范围
位置:bean标签属性位置
语法:scope=""

         属性值:


                singleton========>单例模式====全局唯一====性能好====安全性低(默认方式)
                prototype========>多例模式====全局不唯一====性能不好====安全性高
                ============================以下作用域数据web模块===============================
                request========>一次请求创建一个对象
                session========>一个会话创建一个对象

beans.xml

 <!-- =========================bean的作用域============================== -->
    <bean id="student" class="com.zkt.pojo.Student" scope="prototype"></bean>
    <bean id="student" class="com.zkt.pojo.Student" scope="singleton"></bean>

测试

public class Test01 {
    public static void main(String[] args) {
        //1.加载spring主配置文件,获取spring核心对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");

        Student student1 = (Student) applicationContext.getBean("student");
        Student student2 = (Student) applicationContext.getBean("student");
        System.out.println(student1 == student2);
    }
}

作用域

prototype

singleton

三、spring对于bean的生命周期管理

 单例模式:
            实例化=====>容器创建的时候实例化
            属性赋值
            初始化=====>实例化完成,则自动初始化
                     接口初始化:InitializingBean中的afterPropertiesSet
                     属性初始化:init-method属性绑定方法
            使用操作
            销毁======>容器关闭,单例的bean则自动销毁
                    接口销毁:DisposableBean
                    属性销毁:destroy-method="",完成资源回收

beans.xml

 <!-- =========================bean的生命周期============================== -->
    <bean id="teacher" class="com.zkt.pojo.Teacher" init-method="doinit" destroy-method="dodestory"></bean>

pojo Teacher

public class Teacher implements InitializingBean, DisposableBean {

    private String tname;

    public void setTname(String tname) {
        System.out.println("生命周期===属性赋值");
        this.tname = tname;
    }

    public Teacher() {
        System.out.println("生命周期===实例化");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("生命周期===初始化(接口)");
    }

    public void doinit() {
        System.out.println("生命周期===初始化(属性)");
    }

    public void destroy() throws Exception {
        System.out.println("生命周期===销毁(接口)");
    }

    public void dodestory() {
        System.out.println("生命周期===销毁(属性)");
    }
}

测试

public class Test01 {
    public static void main(String[] args) {
        //1.加载spring主配置文件,获取spring核心对象
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");


        Teacher teacher = (Teacher) applicationContext.getBean("teacher");
        System.out.println(teacher);

        applicationContext.close();
    }
}

四、annotation注解

spring的配置

  •         1.spring2.5前==xml
  •         2.spring2.5后==xml+annotation
  •         3.spring3.0后==JavaConfig+annotation配置类

    spring2.5后=xml+annotation
        目的优化一下代码:

  <bean id="" class="" init-method="" destroy-method="" scope="" autowire="">
                <property></property>
                <constructor-arg></constructor-arg>
            </bean>

1. 注入类 

   替换:<bean id="" class=""></bean>
   位置:类
   语法

      @Component(value="注入容器中的id,如果省略id为类名且首字母小写,value属性名称可以省略")
      @Component
        eg:Class User{}
        <bean id="user" class="com.apesource.包.User"></bean>
                    ||等价于||
        @Component
        Class User{}

<context:component-scan base-package=""></context:component-scan>功能一致

  含义:扫描所有被@Component注解所修饰的类,注入容器

  • @Repository=====>注入数据访问层
  • @Service========>注入业务层
  • @Controller=====>注入控制层

以上三个注解与@Component功能语法一致

 2. 注入基本数据,javaBean

 @Value
含义注入基本数据
替换:<property></property>
修饰:成员变量或对应的set方法

语法:

          @Value("数据内容")
          @Value("${动态获取}")

加载指定资源文件:

<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

@Autowired
替换:DI实现javaBean注入
语法:@Autowired(required = "true-默认、false、是否必须进行装配")
修饰:成员变量或对应的构造方法
含义
按照通过构造方法进行“类型装配”,构造方法可以省略
注意:

  • 1.默认是按照类型装配且同构造方法
  • 2.若容器中有一个类型可以与之匹配则装配成功,若没有一个类型可以匹配则报错NoSuchBeanDefinitionException
  • 3.若容器中有多个类型可以与之匹配,则自动切换为按照名称装配,若名称没有对应,则报错 NoUniqueBeanDefinitionException

3.其他注解

@Primary

  • 含义:首选项,当类型冲突的情况下,此注解修饰的类被列为首选(备胎扶正)
  • 修饰:类 
  • 注意:不能单独使用,必须与@Component....联合使用

 @Qualifier(value="名称")

  • 含义:按照名称装配
  • 修饰:成员变量
  • 注意:不能单独使用,必须与@Autowired联合使用

@Resource(name="名称")

  • 含义:按照名称装配
  • 修饰:成员变量
  • 注意:单独使用

@Scope

  • 含义:配置类的作用域
  • 修饰:类
  • 注意:不能单独使用,必须与@Component....联合使用
    • @Scope("prototype")
    • @Scope("singleton")
    • @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    • @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)       

@PostConstruct:初始化,修饰方法 替换:init-method
@PreDestroy:销毁,修饰方法 替换:destory-method   

实现

applicationContext.xml

​
<!--    扫描包-->
    <context:component-scan base-package="com.zkt"/>
    <!-- 加载指定资源文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

​

controller

public interface IUserController {
    public void insert();
}

@Controller
public class UserControllerImp implements  IUserController{

    @Autowired
   private IUserService service;

    @Override
    public void insert() {
        System.out.println("====controller的新增====");
        service.insert();
    }
}

dao

public interface IUserDao {
    public void insert();
}

@Repository
//@Primary
public class UserDaoImp implements  IUserDao{

//    @Value("驱动")
//    private String dirver;
//    @Value("路径")
//    private String url;
//    @Value("用户")
//    private String username;
//    @Value("密码")
//    private String password;


    @Value("${msg1}")
    private String dirver;
    @Value("${msg2}")
    private String url;
    @Value("${msg3}")
    private String username;
    @Value("${msg4}")
    private String password;

  

    public void insert() {
        System.out.println("====dao的新增====");
    }
}


@Repository(value = "dao2")
public class UserDaoImpCopy implements  IUserDao{
    
    public void insert() {
        System.out.println("====dao2的新增====");
    }
}

service

public interface IUserService {
    public void insert();
}

@Service
public class UserServiceImp implements IUserService {

    @Autowired
//    @Qualifier(value = "dao2")
//    @Resource(name = "dao2")
    private IUserDao dao;

    public void insert() {
        System.out.println("====service的新增====");
        dao.insert();
    }
}

pojo

@Component(value = "stu")
//@Scope("prototype")
//@Scope("singleton")
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class Student {
    private String stuName;
    private String stuHobby;
    private int stuAge;



    public Student() {
        System.out.println("===》执行studnet的无参构造方法");
    }

 
}

测试

public class Test01 {
    public static void main(String[] args) {
        //1.加载容器
        ApplicationContext applicationContext =  new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.获取对象
//        Student student = (Student) applicationContext.getBean("stu");
//        System.out.println(student);
//
//        IUserController controller = (IUserController) applicationContext.getBean("userControllerImp");
//        controller.insert();

//        IUserDao dao = (IUserDao) applicationContext.getBean("userDaoImp");
//        System.out.println(dao);


        //scope 测试
        Student student1 = (Student)applicationContext.getBean("stu");
        Student student2 = (Student)applicationContext.getBean("stu");
        System.out.println(student1==student2);
    }
}
 @Component(value="注入容器中的id,如果省略id为类名且首字母小写,value属性名称可以省略")

 @Value

@Primary @Qualifier(value="名称")@Resource(name="名称")@Scope("prototype")@Scope("singleton")

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)

五、javaconfig 

spring的配置

  • 1.spring2.5前==xml
  • 2.spring2.5后==xml+annotation
  • 3.spring3.0后==JavaConfig+annotation配置类

spring中的新注解
@Configuration

  • 作用:指定当前类是一个配置类,替代applicationContext.xml文件
  • 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。

@ComponentScan

  • 作用:用于通过注解指定spring在创建容器时要扫描的包
  • 替换:
<context:component-scan base-package="com.apesource"></context:component-scan>

@PropertySource

  • 作用:用于指定properties文件的位置
  • 属性:value:指定文件的名称和路径。
  • 替换:
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

@Bean

  • 作用:用于把当前方法的返回值作为bean对象存入spring的容器中
  • 属性:name:用于指定bean的id。当不写时,默认值是当前方法的名称

@Import

  • 作用:用于导入其他的配置类
  • 属性:value:用于指定其他配置类的字节码。
  • 例子:@Import(SystemSpringConfig.class)

实现 

config

@Configuration
@ComponentScan(basePackages = "com.zkt")
@PropertySource(value = "classpath:jdbc.properties")
@Import(DataSourceConfig.class)
public class ApplicationConfig {

    @Bean
    public Student stu1() {
        return new Student();
    }

    @Bean(name = "abc")
    public Student stu2() {
        return new Student();
    }

    @Bean("time")
    public Date date() {
        return new Date();
    }

//    @Bean
//    public IUserDao dao() {
//        return new UserDaoImp();
//    }
//
//    @Bean
//    public IUserService service() {
//        return new UserServiceImp(dao());
//    }
//
//    @Bean
//    public IUserController controller() {
//        return new UserControllerImp(service());
//    }
}
@Configuration
public class DataSourceConfig {

    @Bean
    public IUserDao dao() {
        return new UserDaoImp();
    }

    @Bean
    //@Autowired默认有 可写 可不写
    public IUserService service(@Autowired IUserDao dao) {
        return new UserServiceImp(dao);
    }

    @Bean
    public IUserController controller(/*@Autowired*/IUserService service) {
        return new UserControllerImp(service);
    }
}

dao

public interface IUserDao {
    public void insert();
}

public class UserDaoImp implements IUserDao {


    @Value("${msg1}")
    private String dirver;
    @Value("${msg2}")
    private String url;
    @Value("${msg3}")
    private String username;
    @Value("${msg4}")
    private String password;


    public void insert() {
        System.out.println("====dao的新增====");
        System.out.println(dirver);
        System.out.println(url);
        System.out.println(username);
        System.out.println(password);

    }
}

service

public interface IUserService {
    public void insert();
}

public class UserServiceImp implements IUserService {

//    @Autowired
    private IUserDao dao;

    public UserServiceImp(IUserDao dao) {
        this.dao = dao;
    }

    public void insert() {
        System.out.println("====service的新增====");
        dao.insert();
    }
}

controller

public interface IUserController {
    public void insert();
}


public class UserControllerImp implements  IUserController{

//    @Autowired
   private IUserService service;

    public UserControllerImp(IUserService service) {
        this.service = service;
    }

    @Override
    public void insert() {
        System.out.println("====controller的新增====");
        service.insert();
    }
}

pojo

public class Student {

}

test

public class Test01 {
    public static void main(String[] args) {
        //1.加载容器
        ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(ApplicationConfig.class);

        //2.获取对象
        Student stu1 = (Student) applicationContext.getBean("stu1");
        Student stu2 = (Student) applicationContext.getBean("abc");
        System.out.println(stu1);
        System.out.println(stu2);


        IUserController controller = (IUserController) applicationContext.getBean("controller");
        controller.insert();

//        IUserDao dao = (IUserDao) applicationContext.getBean("userDaoImp");
//        System.out.println(dao);
        
    }
}

两者等价

六、实现单表增删改查 (spring)

1. xml实现

初始准备

poi.xml

<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-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- dbutil -->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>

applicationContext.xml

<!-- 加载文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 注入数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${msg1}"/>
<property name="jdbcUrl" value="${msg2}"/>
<property name="user" value="${msg3}"/>
<property name="password" value="${msg4}"/>
</bean>
<!-- 注入queryRunner -->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"/>
</bean>
<!-- 注入dao -->
<bean id="dao" class="com.apesource.dao.AccountDaoImp">
<property name="queryRunner" ref="queryRunner"/>
</bean>
<!-- 注入service -->
<bean id="service" class="com.apesource.service.AccountServiceImp">
<property name="dao" ref="dao"/>
</bean>
<!-- 注入controller -->
<bean id="controller" class="com.apesource.controller.AccountControllerImp">
<property name="service" ref="service"/>
</bean>

jdbc.properties

msg1=com.mysql.cj.jdbc.Driver
msg2=jdbc:mysql://localhost:3306/javaee2404?serverTimezone=GMT
msg3=root
msg4=123456

dao 

public interface IAccountDao {
    public void save(Account account);
    public void deleteById(int id);
    public void updateById(Account account);
    public List<Account> findAll();
    public Account findByName(String name);

}


public class AccountDaoImp implements IAccountDao{

    //装配QueryRunner
    QueryRunner queryRunner;

    public void setQueryRunner(QueryRunner queryRunner) {
        this.queryRunner = queryRunner;
    }

    @Override
    public void save(Account account) {
        try {
            queryRunner.update("insert into  account(aname,amoney) value(?,?)",account.getAname(),account.getAmoney());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    public void deleteById(int id) {
        try {
            queryRunner.update("delete from account where aid = ?",id);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    public void updateById(Account account) {
        try {
            queryRunner.update("update account set aname=?,amoney=? where aid=?",account.getAname(),account.getAmoney(),account.getAid());
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    public List<Account> findAll() {
        try {
           return  queryRunner.query("select * from account",new BeanListHandler<Account>(Account.class));
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public Account findByName(String name) {
        try {
            return  queryRunner.query("select * from account where aname=?",new BeanHandler<Account>(Account.class),name);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }
}

service

public interface IAccountService {
    public void save(Account account);
    public void deleteById(int id);
    public void updateById(Account account);
    public List<Account> findAll();
    public Account findByName(String name);

}

public class AccountServiceImp implements IAccountService {

    //装配dao
    IAccountDao dao;

    public void setDao(IAccountDao dao) {
        this.dao = dao;
    }

    @Override
    public void save(Account account) {
        dao.save(account);
    }

    @Override
    public void deleteById(int id) {
        dao.deleteById(id);
    }

    @Override
    public void updateById(Account account) {
        dao.updateById(account);
    }

    @Override
    public List<Account> findAll() {
        return dao.findAll();
    }

    @Override
    public Account findByName(String name) {
        return dao.findByName(name);
    }
}

controller

public interface IAccountController {
    public void save(Account account);
    public void deleteById(int id);
    public void updateById(Account account);
    public List<Account> findAll();
    public Account findByName(String name);

}

public class AccountControllerImp implements IAccountController {

    //装配SERVICE
    IAccountService service;

    public void setService(IAccountService service) {
        this.service = service;
    }

    @Override
    public void save(Account account) {
        service.save(account);
    }

    @Override
    public void deleteById(int id) {
        service.deleteById(id);
    }

    @Override
    public void updateById(Account account) {
        service.updateById(account);
    }

    @Override
    public List<Account> findAll() {
        return service.findAll();
    }

    @Override
    public Account findByName(String name) {
        return service.findByName(name);
    }
}

pojo

public class Account implements Serializable {
    private int aid;
    private String aname;
    private int amoney;
get set 构造 tostring ..
}

test 使用junit

    IAccountController controller = null;
    ClassPathXmlApplicationContext applicationContext = null;

    @Before
    public void beforeMethod(){
        applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        controller = (IAccountController) applicationContext.getBean("controller");
    }

    @After
    public void afterMethod(){
        applicationContext.close();
    }


    @Test
    public void show1(){
        controller.save(new Account("李世伟",2000));
        controller.save(new Account("马宇航",2000));

    }

    @Test
    public void show2(){
        List<Account> all = controller.findAll();
        for (int i = 0; i < all.size(); i++) {
            Account account =  all.get(i);
            System.out.println(account);
        }
    }
}
@RunWith(SpringJUnit4ClassRunner.class)//运行环境
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test02 {


    @Autowired
    IAccountController controller;


    @Test
    public void show1(){
        controller.save(new Account("李世伟",2000));
        controller.save(new Account("马宇航",2000));

    }

    @Test
    public void show2(){
        List<Account> all = controller.findAll();
        for (int i = 0; i < all.size(); i++) {
            Account account =  all.get(i);
            System.out.println(account);
        }
    }
}

2. annotation注解

只需要加上注解就行 其余不变

dao

service

controller

applicationContext.xml

 <!--    扫描包-->
    <context:component-scan base-package="com.zkt"/>
    <!-- 加载指定资源文件 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!-- 注入数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${msg1}"/>
        <property name="jdbcUrl" value="${msg2}"/>
        <property name="user" value="${msg3}"/>
        <property name="password" value="${msg4}"/>
    </bean>
    <!-- 注入queryRunner -->
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
        <constructor-arg name="ds" ref="dataSource"/>
    </bean>

测试 同上

3. javaconfig

没有xml 文件了

dao service controller 不变 只需要将xml文件 通过配置类实现就行

config

@Configuration
@ComponentScan(basePackages = "com.zkt")
@Import(DataSourceConfig.class)
public class ApplicationConfig {
}
@Configuration
@PropertySource(value = "classpath:jdbc.properties")
public class DataSourceConfig {
    @Value("${msg1}")
    private String driver;
    @Value("${msg2}")
    private String url;
    @Value("${msg3}")
    private String uname;
    @Value("${msg4}")
    private String upwd;

//    <!-- 注入数据源 -->
//    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
//        <property name="driverClass" value="${msg1}"/>
//        <property name="jdbcUrl" value="${msg2}"/>
//        <property name="user" value="${msg3}"/>
//        <property name="password" value="${msg4}"/>
//    </bean>

    public DataSource dataSource() {
        try {
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
            comboPooledDataSource.setDriverClass(driver);
            comboPooledDataSource.setJdbcUrl(url);
            comboPooledDataSource.setUser(uname);
            comboPooledDataSource.setPassword(upwd);
            return comboPooledDataSource;
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return null;
    }
    //        <!--注入QueryRunner-->
//    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
//        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
//    </bean>
    @Bean
    public QueryRunner queryRunner() {
        return new QueryRunner(dataSource());
    }
}

其余同上 

七、面试题

1-5 见spring1

6. 什么是Spring 的bean

  • ●简单来说,bean 代表被IOC容器管理的对象
  • ●我们通过配置文件或注解,告诉IOC容器帮助我们管理哪些对象

7. 将一个类声明为Bean的注解有哪些?

  • ●@Component:定义通用bean的注解,可标注任意类为 bean。如果一个 bean 不知道属层,可以使用 @component 注解标注
  • ●@Repository:定义数据访问层bean的注解
  • ●@Service:定义业务层bean的注解
  • ●@Controller:定义控制器bean的注解 

8. @Component和@Bean的区别是什么?

  • ●@Component 注解作用于类,而 @bean 注解作用于方法
  • ●@Component 通常是通过类路径扫描来实现自动扫描并完成装配 bean 到 Spring IOC 容器
  • ●@Bean 注解通常用于注解某个方法,告诉了 spring ioc 容器,该方法的返回实例是一个bean  

9. @Autowired和@Resource的区别是什么? 

  • ●@Autowired 是 Spring 提供的注解,@Resource 是 JDK 提供的注解
  • ●@Autowired 默认的注入方式为 bytype (按类型自动注入),@Resource 默认注入方式为 byname (按名称自动注入)

10. Spring框架中的常见注入方式有几种?  

●关键字: 整体介绍三种注入方式、分别介绍每个注入方式的细节
●Spring IOC 有三种注入方式:构造注入、setter注入、属性注入
        ○构造注入:使用构造方法注入 bean
        ○setter注入:使用setter方法注入 bean
        ○属性注入:使用成员属性注入bean,不推荐。原因:使用私有的成员属性变量,依靠反射实现,破坏封装,只能依靠IOC 容器实现注入,不严谨

11. Spring中常见的ApplicationContext实现类有哪些?

  • ●关键字:分别介绍每种实现类或子接
  • ●ClassPathXmlApplicationContext:根据项目类路径classpath下的配置文件加载 bean(通过相对路径加载主配置文件)
  • ●FileSystemXmlApplicationContext:根据当前磁盘的一个绝对系统文件路径下的配置文件加载bean (通过绝对路径加载主配置文件通过绝对路径加载主配置文件)
  • ●AnnotationConfigApplicationContext:根据读取到的注解加载 bean
  • ●WebApplicationContext: web容器下按照配置文件加载 bean

12. BeanFactory和ApplicationContext有什么区别? 

  • ●关键字:两者之间的关系、区别与不同、bean的创建加载方式
  • ●两者之间的关系: BeanFactory 和ApplicationContext 是 Spring 的两大核心接口,都可当做 Spring 的容器

两者区别∶

  • ●Beanfactory是 Spring 里面最底层的接口,是IOC 的核心,定义了IOC 的基本功能,包含了各种 Bean 的定义、加载、实例化,依赖注入和生命周期管理等行为
  • ●ApplicationContext 接口作为 BeanFactory 接口的子接口,包含 BeanFactory 所具备的功能外,还提供了其它框架功能:继承 MessageSource(支持国际化),资源文件访问、可同时加载多个配置文件、可以通过监听器管理 Bean 的生命周期

●Bean的创建加载方式:

  • BeanFactroy 采用的是延迟加载形式来注入 bean,只有在使用到某个 bean 时,才对该 bean 进行加载实例化。这样不能提前发现一些存在的 spring 的配置问题。如果 bean 的某一个属性没有注入,beanfactory 加载后,直至第一次使用调用 getbean()方法才会抛出异常
  • ○ApplicationContext是在容器启动时,一次性创建了所有的 bean。这样,在容器启动时, 我们就可以发现 spring 中存在的配置错误,这样有利于检查所依赖属性是否注入。 运行的时候速度比较快,因为它们已经创建好了。相对于BeanFactory,ApplicationContext 唯一的不足是占用内存空间,当用程序配置 bean 较多时,程序启动较慢

13. Spring 框架启动流程(了解) 

●关键字:初始化spring容器、注册BeanDefinition、刷新容器
●首先,初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器

  • ○实例化 BeanFactory【 Defaultlistablebeanfactory 】工厂,用于生成 bean 对象
  • ○实例化 beandefinitionreader,用于读取 spring 配置文件或注解,将配置文件中 spring 需要管理的组件类,转化成 beandefinition 对象,( beandefinition 是 spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,例如: bean的id,是否 单例,是否懒加载等)
  • ○实例化classpathbeandefinitionscanner路径扫描器,用于对指定的包目录进行扫描查找bean 对象

●将配置类的beandefinition注册到容器中
●调用refresh()方法刷新容器

  • ○preparerefresh)刷新前的预处理
  • ○obtainffreshbeanfactory(): 获取在容器初始化时创建的BeanFactory
  • ○preparebeanfactory(beanfactory):BeanFactory的预处理工作,向容器中添加一些组件
  • ○postprocessbeanfactory(beanfactory):子类重写该方法,可以实现在beanfactory创建并预处理完成以后做进一步的设置
  • ○invokebeanffactorypostprocessors(beanfactory):在beanfactory标准初始化之后执行 beanfactorypostprocessor的方法,即pbeanffactory的后置处理器
  • ○registerbeanpostprocessors(beanfactory):向容器中注册bean的后置处理器 beanpostprocessor,它的主要作用是干预spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
  • ○initmessagesource():初始化messagesource组件,主要用于做国际化功能,消息绑定与消解析
  • ○initapplicationeventmulticaster():初始化事件派发器,在注册监听器时会用到
  • ○onrefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑
  • ○registerlisteners():注册监听器:将容器中所有的applicationlistener注册到事件派发器中,并派发之前步骤产生的事件
  • ○finishbeanfactorylnitialization( beanfactory ):初始化所有剩下的单实例bean,核心方法prelnstantiatesingletons(),会调用getBean()方法创建对象
  • ○finishRefresh():发布BeanFactory容器刷新完成事件

14. Spring 框架中的Bean的作用域 

  • singletonSpring为该bean对象只会创建唯一实例,Spring中的bean默认都是单例
  • prototype:每次获取bean,Spring会创建一个新的bean实例
  • request:每一次http请求,Spring会创建一个新的bean实例
  • session:不同的http会话,Spring会创建不同的bean实例

15. Spring 框架中的Bean的线程安全

  • ●对于prototype作用域的bean,每次都创建一个新对象,也就是线程之间不存在bean共享,因此不会有线程安全问题
  • ●对于singleton作用域的bean ,所有的线程都共享一个单例状态的bean,存在资源竞争,因此是存在线程安全问题的
  • ●解决办法:对于singleton作用域的单例bean,它的线程安全问题,常见有两种解决办法
    • ○在bean中尽量避免定义可变的成员变量(用于保存数据的成员变量)
    • ○在类中定义一个ThreadLocal成员变量,将需要可变的成员变量保存在 ThreadLocal

;