Spring5学习:IOC容器-Bean管理-3


前言

跟随尚硅谷学习Spring5
IOC容器

一、IOC 操作 Bean 管理(bean 生命周期)

  • 生命周期
    • 从对象创建到对象销毁的过程
  • bean生命周期
    • 通过构造器创建 bean 实例(无参数构造)
    • 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
    • 调用 bean 的初始化的方法(需要进行配置初始化的方法)
    • bean 可以使用了(对象获取到了)
    • 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
  • 演示 bean 生命周期
     创建类,定义属性和对应的 set 方法
package com.atguigu.spring5.dependencyInjection.beanLifeCycle;

public class Orders {

    public Orders() {
        System.out.println("Orders: 第一步 执行无参数构造创建bean实例");
    }

    private String orderName;

    public void setOrderName(String orderName) {
        this.orderName = orderName;
        System.out.println("Orders: 第二步 调用set方法设置属性值");
    }

    @Override
    public String toString() {
        return "Orders{" +
                "orderName='" + orderName + '\'' +
                '}';
    }

    // 创建执行的初始化方法
    public void myCustomInitMethod() {
        System.out.println("Orders: 第三步 调用初始化方法");
    }

    // 创建执行的销毁方法
    public void myCustomDestroyMethod() {
        System.out.println("Orders: 第五步 调用销毁方法");
    }
}

  在 spring配置文件配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="orders" class="com.atguigu.spring5.dependencyInjection.beanLifeCycle.Orders" init-method="myCustomInitMethod" destroy-method="myCustomDestroyMethod">
        <property name="orderName" value="手机"/>
    </bean>
</beans>

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.beanLifeCycle.Orders;
import com.atguigu.spring5.dependencyInjection.beanLifeCycle.Orders3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanLifeCycleTest {

    @Test
    public void testBeanLifeCycle() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanLifeCycle.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("第四步 获取创建的bean实例对象");
        System.out.println(orders);
        // 手动让bean实例销毁,来调用destroy方法
        ((ClassPathXmlApplicationContext) context).close();
    }
}
  • 在bean的基础五步生命周期外,还有额外的两步,bean 的后置处理器, bean 生命周期有七步
    • 通过构造器创建 bean 实例(无参数构造)
    • 为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
    • 把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
    • 调用 bean 的初始化的方法(需要进行配置初始化的方法)
    • 把 bean 实例传递 bean 后置处理器的方法postProcessAfterInitialization
    • bean 可以使用了(对象获取到了)
    • 当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法)
  • 演示添加后置处理器效果
     创建类,定义属性和对应的 set 方法
package com.atguigu.spring5.dependencyInjection.beanLifeCycle;

public class Orders {

    public Orders() {
        System.out.println("Orders: 第一步 执行无参数构造创建bean实例");
    }

    private String orderName;

    public void setOrderName(String orderName) {
        this.orderName = orderName;
        System.out.println("Orders: 第二步 调用set方法设置属性值");
    }

    @Override
    public String toString() {
        return "Orders{" +
                "orderName='" + orderName + '\'' +
                '}';
    }

    // 创建执行的初始化方法
    public void myCustomInitMethod() {
        System.out.println("Orders: 第三步 调用初始化方法");
    }

    // 创建执行的销毁方法
    public void myCustomDestroyMethod() {
        System.out.println("Orders: 第五步 调用销毁方法");
    }
}
package com.atguigu.spring5.dependencyInjection.beanLifeCycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPost implements BeanPostProcessor {

    // 后置处理器 - 初始化前
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization() - 在bean初始化之前执行的方法");
        return bean;
    }

    // 后置处理器 - 初始化后
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization() - 在bean初始化之后执行的方法");
        return bean;
    }
}

  在 spring配置文件配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--添加了初始化前后的方法,方法只做打印处理,来测试后置处理器是否正常工作
        以下是bean里面写的打印方法,方法名随意:
            init-method="myCustomInitMethod" destroy-method="myCustomDestroyMethod"
        若不添加上面的init-method和destroy-method,后置处理器同样会作用域该bean
    -->
    <bean id="orders" class="com.atguigu.spring5.dependencyInjection.beanLifeCycle.Orders" init-method="myCustomInitMethod" destroy-method="myCustomDestroyMethod">
        <property name="orderName" value="电脑"/>
    </bean>
    
    <!--myBeanPost的bean实现类,实现了BeanPostProcessor接口,则对于该配置文件的所有bean实例化前后都会执行该实例化前后的后置处理器!-->
    <bean id="myBeanPost" class="com.atguigu.spring5.dependencyInjection.beanLifeCycle.MyBeanPost"/>
</beans>

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.beanLifeCycle.Orders;
import com.atguigu.spring5.dependencyInjection.beanLifeCycle.Orders3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanLifeCycleTest {

        @Test
    public void testBeanLifeCyclePostProcessor() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanLifeCyclePostProcessor.xml");

        /**
         * getBean()方法读取【任意一个】配置文件里的对象,所有配置文件里的对象皆被初始化
         */
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("所有通用:第四步 获取创建的bean实例对象");
        System.out.println(orders);
        // 手动让bean实例销毁,来调用destroy方法
        ((ClassPathXmlApplicationContext) context).close();
    }
}

二、IOC 操作 Bean 管理(xml 自动装配)

 创建类,定义属性和对应的 set 方法

package com.atguigu.spring5.dependencyInjection.autowired;

public class Employee {

    private Department department;

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "department=" + department +
                '}';
    }
}
package com.atguigu.spring5.dependencyInjection.autowired;

public class Department {
}

  在 spring 配置文件中进行配置,对比非自动装配和自动装配

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--非自动装配写法-->
    <!--
    <bean id="dept" class="com.atguigu.spring5.dependencyInjection.autowired.Department"/>

    <bean id="emp" class="com.atguigu.spring5.dependencyInjection.autowired.Employee">
        <property name="department" ref="dept"></property>
    </bean>
    -->


    <!--实现自动装配
        bean标签属性autowire,配置自动装配
        autowire属性常用两个值:
            byName - 根据属性名称注入
            byType - 根据属性类型注入
    -->
    <bean id="dept" class="com.atguigu.spring5.dependencyInjection.autowired.Department"/>

<!--    <bean id="dept2" class="com.atguigu.spring5.dependencyInjection.autowired.Department"/>-->
<!--    <bean id="emp" class="com.atguigu.spring5.dependencyInjection.autowired.Employee" autowire="byName"/>-->
    <bean id="emp" class="com.atguigu.spring5.dependencyInjection.autowired.Employee" autowire="byType"/>
</beans>

  测试:

package com.atguigu.sprint5;
import com.atguigu.spring5.dependencyInjection.autowired.Employee;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanAutowiredTest {

    @Test
    public void testBeanOriginalApproach() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAutowired.xml");
        Employee emp = context.getBean("emp", Employee.class);
        System.out.println(emp);
    }
}

三、IOC 操作 Bean 管理(外部属性文件)

  • 直接配置数据库信息
      配置德鲁伊连接池
      引入德鲁伊连接池依赖 jar 包
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--直接配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
</beans>
  • 引入外部属性文件配置数据库连接池
      创建外部属性文件, properties格式文件,写数据库信息
jdbc.driverClassName="com.mysql.jdbc.Driver"
jdbc.url="jdbc:mysql://localhost:3306/test"
jdbc.username="root"
jdbc.password="root"
  • 把外部 properties 属性文件引入到 spring 配置文件中
      引入 context 名称空间
      在 spring 配置文件使用标签引入外部属性文件
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
                           
    <!--
        1. 引入外部属性文件,使用引入context命名空间的context标签
        2. 使用${}表达式读取外部属性文件的值
    -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

  测试:

package com.atguigu.sprint5;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanExternalConfigTest {

    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanDruid.xml");
        DruidDataSource dataSource = context.getBean("dataSource", DruidDataSource.class);
        System.out.println(dataSource);
    }
}

四、IOC 操作 Bean 管理(基于注解方式)

  • 什么是注解
    • 注解是代码特殊标记,格式: @注解名称(属性名称=属性值, 属性名称=属性值…)
    • 使用注解,注解作用在类上面,方法上面,属性上面
    • 使用注解目的:简化 xml 配置
  • Spring 针对 Bean 管理中创建对象提供注解
    • @Component 普通组件
    • @Service 用于业务逻辑层
    • @Controller 用于Web层
    • @Repository 用于Dao层
      上面四个注解功能是一样的,都可以用来创建 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 https://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
                           
    <!--开启组件扫面
        方式1:如果扫描多个包, 多个包使用逗号隔开
        方式2:扫描包上层目录
    -->
<!--    <context:component-scan base-package="com.atguigu.spring5.dependencyInjection.annotations.dao, com.atguigu.spring5.dependencyInjection.annotations.service"/>-->
    <context:component-scan base-package="com.atguigu.spring5.dependencyInjection.annotations"/>
</beans>

  在类上面添加创建对象注解

package com.atguigu.spring5.dependencyInjection.annotations.service;

import org.springframework.stereotype.Component;

@Component // 写法1,不加括号内容,默认值类名首字母小写
//@Component(value="userService") // 写法2,等同于<bean id="userService class=".."/>
public class UserService {

    public void add() {
        System.out.println("service add.....");
    }
}

 开启组件扫描细节配置

  扫描哪些类

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

    <!--开启组件扫面:include参数
        use-default-filters="false" - 表示步使用默认filter,自己配置filter
    -->
    <context:component-scan base-package="com.atguigu.spring5.dependencyInjection.annotations" use-default-filters="false">
        <!--只扫描带@Controller的类-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

</beans>

  不扫描哪些类

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

    <!--开启组件扫面:exclude参数-->
    <context:component-scan base-package="com.atguigu.spring5.dependencyInjection.annotations">
        <!--只扫描带@Controller的类-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
</beans>

 基于注解方式实现属性注入

  • @Autowired:根据属性类型进行自动装配
  • @Qualifier:根据名称进行注入
  • @Resource:可以根据类型注入,可以根据名称注入
  • @Value:注入普通类型属性

  @Autowired:根据属性类型进行自动装配

  把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解

package com.atguigu.spring5.dependencyInjection.annotations.dao;

public interface BookDao {
    public void add();
}
package com.atguigu.spring5.dependencyInjection.annotations.dao;

import org.springframework.stereotype.Repository;

@Repository
public class BookDaoImpl implements BookDao {

    public void add() {
        System.out.println("BookDaoImpl.add() - book dao add...");
    }
}

  在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解

package com.atguigu.spring5.dependencyInjection.annotations.service;

import com.atguigu.spring5.dependencyInjection.annotations.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookServiceAutowired {

    // service上调用dao,需要定义dao类型属性
    // 注意这里不需要添加setter方法
    @Autowired // 根据类型进行注入:byType
    private BookDao bookDao;

    public void add() {
        System.out.println("BookServiceAutowired.add() - book service add.....");
        // 为了体现属性注入效果,在这里打印dao方法
        bookDao.add();
    }
}

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.annotations.service.BookServiceAutowired;
import com.atguigu.spring5.dependencyInjection.annotations.service.UserServiceQualifier;
import com.atguigu.spring5.dependencyInjection.annotations.service.ValueNormalDataInjectionService;
import com.atguigu.spring5.dependencyInjection.annotations.service.WorkerServiceResource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanAnnotationsTest {

    @Test
    public void testAutowired() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAnnotations.xml");
        BookServiceAutowired bookServiceAutowired = context.getBean("bookServiceAutowired", BookServiceAutowired.class);
        bookServiceAutowired.add();
    }

  @Qualifier:根据名称进行注入

  这个@Qualifier 注解的使用,要上面@Autowired 一起使用

package com.atguigu.spring5.dependencyInjection.annotations.dao;

public interface UserDao {
    public void add();
}

  当一个接口有多个实现类的时候

package com.atguigu.spring5.dependencyInjection.annotations.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {

    public void add() {
        System.out.println("UserDaoImpl.add() - user dao add.....");
    }
}
package com.atguigu.spring5.dependencyInjection.annotations.dao;

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoImpl implements UserDao {

    public void add() {
        System.out.println("UserDaoImpl.add() - user dao add.....");
    }
}
package com.atguigu.spring5.dependencyInjection.annotations.dao;

import org.springframework.stereotype.Repository;

@Repository(value="userDaoImpl2")
public class UserDaoImpl2 implements UserDao {

    public void add() {
        System.out.println("UserDaoImpl2.add() - user dao add.....");
    }
}

  有多个实现类的时候,指定名称选择对应实现类来注入指定实现类类依赖对象

package com.atguigu.spring5.dependencyInjection.annotations.service;

import com.atguigu.spring5.dependencyInjection.annotations.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceQualifier {

    // service上调用dao,需要定义dao类型属性
    // 注意这里不需要添加setter方法
    @Autowired // 根据类型进行注入:byType
    @Qualifier(value="userDaoImpl2") // 假如有多个实现类的时候,指定名称选择对应实现类来注入指定实现类类依赖对象
    private UserDao userDao;

    public void add() {
        System.out.println("UserServiceQualifier.add() - user service add.....");
        // 为了体现属性注入效果,在这里打印dao方法
        userDao.add();
    }
}

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.annotations.service.BookServiceAutowired;
import com.atguigu.spring5.dependencyInjection.annotations.service.UserServiceQualifier;
import com.atguigu.spring5.dependencyInjection.annotations.service.ValueNormalDataInjectionService;
import com.atguigu.spring5.dependencyInjection.annotations.service.WorkerServiceResource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanAnnotationsTest {

    @Test
    public void testQualifier() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAnnotations.xml");
        UserServiceQualifier userServiceQualifier = context.getBean("userServiceQualifier", UserServiceQualifier.class);
        userServiceQualifier.add();
    }
}

  @Resource:可以根据类型注入,可以根据名称注入

  创建类

package com.atguigu.spring5.dependencyInjection.annotations.dao;

public interface WorkerDao {
    public void add();
}
package com.atguigu.spring5.dependencyInjection.annotations.dao;

import org.springframework.stereotype.Repository;

//@Repository // 根据类型注入
@Repository(value = "workerDaoImpl")  // 根据名称注入
public class WorkerDaoImpl implements WorkerDao{

    public void add() {
        System.out.println("WorkerDaoImpl.add() - worker dao add.....");
    }
}

  使用类型注入和名称注入结果相同

package com.atguigu.spring5.dependencyInjection.annotations.service;

import com.atguigu.spring5.dependencyInjection.annotations.dao.WorkerDao;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class WorkerServiceResource {

//    @Resource // 根据类型注入
    @Resource(name="workerDaoImpl") // 根据名称注入
    private WorkerDao workerDao;

    public void add() {
        System.out.println("WorkerServiceResource.add() - worker service add.....");
        workerDao.add();
    }
}

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.annotations.service.BookServiceAutowired;
import com.atguigu.spring5.dependencyInjection.annotations.service.UserServiceQualifier;
import com.atguigu.spring5.dependencyInjection.annotations.service.ValueNormalDataInjectionService;
import com.atguigu.spring5.dependencyInjection.annotations.service.WorkerServiceResource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanAnnotationsTest {

    @Test
    public void testResource() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAnnotations.xml");
        WorkerServiceResource workerServiceResource = context.getBean("workerServiceResource", WorkerServiceResource.class);
        workerServiceResource.add();
    }
}

  @Value:注入普通类型属性

package com.atguigu.spring5.dependencyInjection.annotations.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class ValueNormalDataInjectionService {

    @Value(value = "abc")
    private String str;

    public void valueTest() {
        System.out.println("使用@Value注入的值为:" + str);
    }
}

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.annotations.service.BookServiceAutowired;
import com.atguigu.spring5.dependencyInjection.annotations.service.UserServiceQualifier;
import com.atguigu.spring5.dependencyInjection.annotations.service.ValueNormalDataInjectionService;
import com.atguigu.spring5.dependencyInjection.annotations.service.WorkerServiceResource;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanAnnotationsTest {

    @Test
    public void testValue() {
        ApplicationContext context = new ClassPathXmlApplicationContext("beanAnnotations.xml");
        ValueNormalDataInjectionService valueNormalDataInjectionService = context.getBean("valueNormalDataInjectionService", ValueNormalDataInjectionService.class);
        valueNormalDataInjectionService.valueTest();
    }
}

 完全注解开发

  创建配置类,替代xml 配置文件

package com.atguigu.spring5.dependencyInjection.annotations.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration // 作为配置类,替代xml配置文件
/**
 * 开启组件扫面:
 *  方式1:如果扫描多个包, 多个包使用逗号隔开
 *  方式2:扫描包上层目录
 */
//@ComponentScan(basePackages = {"com.atguigu.spring5.dependencyInjection.annotations.dao, com.atguigu.spring5.dependencyInjection.annotations.service"})
@ComponentScan(basePackages = {"com.atguigu.spring5"})
public class SpringConfig {
}

  创建类和接口

package com.atguigu.spring5.dependencyInjection.annotations.dao;

public interface BookDao {
    public void add();
}

  添加创建对象注解

package com.atguigu.spring5.dependencyInjection.annotations.service;

import com.atguigu.spring5.dependencyInjection.annotations.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class BookService {

    // service上调用dao,需要定义dao类型属性
    // 注意这里不需要添加setter方法
    @Autowired // 根据类型进行注入:byType
    private BookDao bookDao;

    public void add() {
        System.out.println("BookServiceAutowired.add() - book service add.....");
        // 为了体现属性注入效果,在这里打印dao方法
        bookDao.add();
    }
}

  测试:

package com.atguigu.sprint5;

import com.atguigu.spring5.dependencyInjection.annotations.config.SpringConfig;
import com.atguigu.spring5.dependencyInjection.annotations.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BeanAnnotationsTest {

    @Test
    public void testAutowired() {
        // 加载配置类
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        BookService bookService = context.getBean("bookService", BookService.class);
        bookService.add();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
int和Integer有什么区别? 答:int是java的原始数据类型,Integer是java为int提供的封装类,java为每个原始数据类型都提供了封装类。 String和StringBuffer的区别? 答:String是不可变的对象,每次对String类型进行改变都相当于产生了一个新的对象,StringBuffer是可变的字符序列,所以如果要经常改变某个字符串的话建议使用StringBuffer。 list、set、map问题? 答:set 不允许重复,无序 list 允许重复,有序 map 成对的数据结构,键值必须具有唯一性 Servlet和CGI的区别? 答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式允许其service方法,一个实例可以服务于多个请求,并且其实例一般不会被销毁,而CGI对每个请求都产生新的进程,服务完后就销毁,所以效率上低于Servlet。 面向对象的特征? 答:1:封装:通过定义类并且给类的属性和方法加上访问控制 2:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。 3:多台:不同对象对统一消息作出不同响应称之为多态 4:抽象:忽略与当前主题无关的那些方面,将注意力集中在与当前目标有关的方面 运行时异常和一般异常有何异同? 答:运行时异常时(JVM)java虚拟机在运行过程中发生的问题,比如:内存溢出等问题。这类异常没法要求程序员去一一捕获并抛出,一般异常是Java类库或程序员自己写的代码发生的错误,这类异常可以由我们去一一捕获并抛出。 多线程几种实现方法,同步? 答:多线程有两种实现方法,一种是继承Thread类或者实现Runnable接口。同步就是在方法返回类型后面加上synchronized。 c#中的委托,事件是不是委托? 答:委托就是将方法作为一个参数带入另一个方法叫做委托,事件是一种特殊的委托。 应用程序域? 答:应用程序域可以理解为一种轻量级的进程,起到安全的作用,占用资源小。 Class.forName作用? 答:调用该访问返回一个以字符串指定类名的类对象。 JDO? 答:JDO是java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。 CORBA? 答:CORBA标准是公共对象请求代理结构,用途为:用不同的程序设计语言书写,在不同的进程中运行,为不同的操作系统开发。 xml解析技术? 答:常用的DOM、SAX等 DOM:处理大型文件时性能下降的非常厉害,适合对xml的随机访问 SAX:事件驱动型的xml解析方法,适合对xml的顺序访问 jsp常用动作? 答:jsp:include 引入一个文件 jsp:useBean 实例化JavaBean jsp:setProperty 设置JavaBean属性 jsp:getProperty 输出JavaBean属性 jsp:forward 转发 CTS、CLS、CLR分别作何解释? 答:CTS 通用类型系统、CLS 通用语言规范、CLR 公共语言运行时。 Struts1和Struts2原理和区别? 答:Struts1和Struts2是两个完全不同的框架,Struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。Struts2以核心控制器FilterDispatcher为基础,包含了框架内部的控制流程和处理机制。 Hibernate工作原理,Hibernate数据持久化? 答:Hibernate工作原理: 1:读取并解析映射信息,创建SessionFactory 2:打开Session 3:创建事物 4:持久化操作 5:提交事务 6:关闭Session 7:关闭SessionFactory Hibernate持久化:Hibernate根据定义的映射规则将对象持久化保存到数据库,这就实现了对象的持久化。 Spring由那几个模块组成? 答:Spring主要由7个模块组成: 1:Spring核心容器:提供了Spring框架的基本功能 2:Spring AOP:通过配置管理特性 3:Spring ORM:Spring框架集成了若干ORM框架 4:Spring DAO:打开关闭数据库连接 5:Spring WEB:为基于WEB服务的应用程序提供上下文服务 6:Spring Context:向Spring框架提供上下文信息 7:Spring MVC:分离模型、视图、控制器、以便更容易定制 折构函数和虚函数? 答:折构函数式销毁一个类的函数,虚函数是为了C++的动态绑定而设计的。 描述你的编程风格? 答:类名首字母大写,常量一般全部大写,给自己的代码加注释。 控制流程? 答:控制流程一般使用if判断条件。有第二分支,多分支,循环结构。循环本质上也是通过判断来实现的。 多形与继承? 答:多形:一个类中多个同名方法。继承:子类继承父类。 jsp内置对象? 答:request 用户端请求 response 回应 pageContext 网页属性 session 会话 out 输出 page 当前网页 exception 错误网页 application servlet正在执行的内容 config servlet构架部件 Struts模型驱动? 答:封装请求参数。 简述JDBC? 答:JDBC数据库连接,是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问。 什么情况下不建议使用Hibernate? 答:当数据量大,并且表关系复杂的时候不建议使用。 sleep()和wait()有什么区别? 答:sleep()是线程类的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但监控状态依然保持,到时候会自动恢复。 wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。 同步和异步,在什么情况下分别使用? 答:如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步。在很多情况下采用异步往往更有效率。 数据库三大范式? 答:1:确保每列都是不可分割的原子值 2:确保每列都和主键相关 3:确保每列都和主键直接相关,而不是间接相关 单例模式有哪些好处? 答:单例模式是一种比较常见的设计模式,带给我们以下好处: 1:控制资源的使用 2:控制实例的产生数量 3:让多个不相关的两个线程或进程之间实现通信 为什么要用spring? 答:1、主要将各个框架有效的联系起来,缩短实际编程时间。 2、可以将各个框架进行有效的管理和控制,让数据传输安全。 springIOC和DI? 答:控制反转和依赖注入是spring的两大基础作用。主要是将所有组件在spring提供的外部容器中加载。提高安全性,减低耦合性,使各个框架或者类之间的依赖性降低。 什么是声明式的事务管理?为什么要用?spring如何实现声明式的事务管理? 答:声明式的事务管理主要是将在进行对数据库中数据的添加或者修改时需要执行事务管理,主要是为了避免在执行添加或修改的时候添加或修改不完全正确,导致数据丢失。spring使用AOP面向切面的思想进行事务管理的。 spring和Hibernate继承后,定义事务管理特性的时候查询为什么要定义为read-only? 答:因为添加、删除和更新都涉及到了数据库的修改,而查询并未涉及到数据库修改,所以只需要定义只读,这样可以提高效率,进行更加方便的事务管理。 请你谈谈对Hibernate OR映射的理解? 答:将数据库中的每一张表都映射成一个实体。 配置了lazy="true"一定会懒加载吗? 答:不一定,如果在配置中你也使用了fetch属性的话此时lazy就会失效。 Hibernate数据库标识与主键之间的认识? 答:标识是为了方便和简介映射文件,主键是为了让数据不会重复。 为什么每次请求都要创建一个Action对象? 答:Struts2每次请求的时候都会创建一个action实例,这样会保证线程的安全。Struts1只是在第一次请求的时候创建一个action实例,以后每次相同的请求都直接从内存中去读取,它是单例模式,安全性较差。 Struts2是如何实现MVC模式的? 答:在Struts2里面是将每次页面的请求进行处理,然后将请求需要输出的数据转发到需要做数据显示的页面。Struts2只是起到一个数据接收和转接的功能,就是Controller控制器,而传来数据的页面叫view显示层,Struts2将数据提交给进行处理的类叫Model模型层,专门进行数据处理和数据库的连接。 heap和stack有什么区别? 答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成,栈按照后进先出的方式进行处理。堆是栈的一个组成元素。 EJB和JavaBean的区别? 答:EJB不是一般的JavaBean,EJB是企业级的JavaBean,EJB一共分为3种,实体Bean,消息Bean,会话Bean。书写EJB要遵循一定的规范,另外要运行EJB,你需要有相应的EJB容器,比如WebLogic、jboss等,而JavaBean不需要,只需要安装Tomcat就可以了。EJB用于服务端的应用开发,而JavaBean用于客户端应用开发。 触发器? 答:触发器是一种特殊的存储过程,主要通过事件来触发而被执行。 什么是存储过程?用什么调用? 答:存储过程是一个预编译的SQL语句,优点是允许模块化的设计。就是说只需要创建一次,以后再程序中就可以调用多次。使用存储过程比单纯的SQL语句要快,可以用一个命令对象来调用存储过程。 索引优缺点? 答:索引可以提高对数据库中数据的检索,缺点是减慢了数据录入速度,同时也增加了数据库的尺寸大小。 什么是事务?什么是事锁? 答:事务就是被绑定在一起,作为一个逻辑单元执行的SQL语句。如果任何一个操作失败,那么整个就失败。共同失败或共同成功。锁可以保证事务的完整性和并发性。 什么是视图?游标是什么? 答:视图是一种虚拟的表,具有和物理表相同的功能。游标是对查询出来的结果集作为一个单元来有效的处理,可以对结果集的当前行做修改。 select执行顺序? 答:from where group by having select order by Collection和Collections的区别? 答:Collection是集合类的父类,继承它的主要由set和list Collections是针对集合类的帮助类,它提供了一系列针对集合的搜索,排序,线程安全化等操作。 final、finally、finalize的区别? 答:final用于声明属性方法和类,分别表示:属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句的一部分,表示总是执行。 finalize是Object的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。 assert是什么?什么时候用到? 答:断言,可以将断言看成是异常处理的一种高级形式,可以用来判断某个特定的表达式或值是否为真。 接口是否可以继承接口?抽象类是否可以实现接口?抽象类是否可以继承实体类? 答:接口可以继承接口,抽象类可以实现接口,抽象类可以继承实体类。 引用传递和值传递? 答:引用传递:形参改变影响实参 值传递:形参改变不影响实参 当一个线程进入一个对象的synchronized方法后,其他线程是否可进入此对象的其他方法? 答:其他方法前是否加了synchronized关键字,如果没加则能。 说出servlet生命周期? 答:servlet实例化时调用init方法,得到请求时调用service方法,service方法自动派遣doget或dopost方法,最后当实例销毁时调用destroy方法。 error和exception有什么区别? 答:error是指错误,通常程序员不能通过代码来解决。底层环境或硬件问题。 exception是指异常,可以通过代码来解决的问题。 forward和redirect的区别? 答:forward是转发,浏览器跳转后不显示新的地址。 redirect是重定向,浏览器跳转后显示新的地址。 对比之下forward更加高效,并且它有助于隐藏实际地址,但是有些情况则必须使用redirect,否则会报异常。 jsp中动态include和静态include的区别? 答:动态include用jsp:include实现,适用于动态页面,可以携带参数 静态include用include伪码实现,适用于静态页面 math.round(11.5)等于多少?math.round(-11.5)等于多少? 答:Math.round()对数字进行四舍五入 Math.round(11.5)=12 Math.round(-11.5)=11 String s=new String("xyz");创建了几个String Object? 答:创建了两个String对象,一个保存的引用地址,一个保存实际的值。 数组有没有length()这个方法?String呢? 答:数组里面没有length()方法,而是length属性。String有length()这个方法。 swtich()能否作用在byte、long、String上? 答:swtich()传递的应该是一个整数表达式,所以它的值只能是:int、short、char、byte所以long和String都不能作用在swtich()上。 jsp和servlet之间的联系? 答:jsp前段动态页面,servlet是纯java类 jsp被编译之后会转换为servlet执行 java基本数据类型有哪些?String是不是基本数据类型,他们有何区别? 答:基本数据类型8种:int、short、byte、long、float、double、char、boolean String不是基本数据类型,引用数据类型。 区别:基本数据类型比较实用“==”,引用数据类型实用equest,并且引用数据类型存放的是地址而不是具体的值。 写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出bbbhhtccc? 答:String s="bbbwlirbbb"; s.replaceAll("wlirbbb","hhtccc"); 如何将数值型字符转换为数字(Integer,Double)? 答:可以用Integer.parseInt()和Double.parseDouble()方法 如何将数字转换为字符? 答:可以使用String的valueOf()方法。 如何取得1970到现在的毫秒数? 答:可以用getTime()方法。 如何格式化日期? 答:可以用SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd"); 判断是否有子文件?判断是否有子目录?判断文件是否存在? 答:判断是否有子文件使用file.isFile() 判断是否有子目录使用file.isDirectory() 判断文件是否存在使用file.exists() 继承、重载、覆盖问题? 答:继承:子类继承父类,子类可以拥有父类中已定义的方法,并且子类可以修改父类中的方法使其更适合特殊需求。 重载:在一个类中方法名和返回类型相同,参数不同。 覆盖:在子类中覆盖父类的某个方法,要求方法名相同,参数类型相同。 Statement和PreparedStatement之间的区别? 答:Statement比PreparedStatement速度慢 PreparedStatement是预编译,插入时速度高于Statement Statement创建速度很慢,常用选择PreparedStatement Session机制? 答:session机制是一种服务器端机制,服务器使用一种类似于散列表的结构来保存信息。 jsp和servlet中的请求转发分别如何实现? 答:jsp可以使用jsp:forward标签转发 servlet可以使用request.getRequestDispatcher()实现转发 介绍j2ee、j2se、j2me的区别? 答:j2ee(企业版):主要用于企业web开发 j2se(标准版):主要用于web开发,但缺少企业版的一些特性 j2me(微小版):主要用于手机开发 J2ee提供的技术? 答:j2ee提供的技术有EJB、servlet、jsp等。 什么是Application Server? 答:Application Server 应用服务器 简单介绍连接池的优点和原理? 答:数据库连接和关闭是比较花费时间的一件事,而连接池可以提高我们的工作效率。 刚开始创建一定数量的池连接,当需要时从池连接中拿出一个,用完之后再把这个连接重新放回连接池。 Web.xml的作用? 答:Web.xml会在程序启动时执行,如果想在程序刚启动的时候执行一些方法的话可以配置在Web.xml中。 简单介绍您所了解的MVC? 答:在项目中使用MVC模式会使项目分工更加明确,结构更加清晰 M model 模型层:JavaBean V view 视图层:jsp html C controller 控制层:servlet 简单介绍你所了解的XML? 答:XML可扩展标记语言,可以用来标记数据,定义数据结构,是一种允许用户自定义标记的语言 简单介绍您所了解的structs、spring和hibernate? 答:struts:控制层Action,页面标签和Model数据,调用业务层 Spring:Aop管理事务控制,IOC管理各个组件的耦合 Hibernate:负责数据库和对象的映射,负责Dao层 因为你去公司面试,公司让你写笔试,不可能说XX一个题目写两页纸写的太详细,所以以上答案有的可能比较简短,没有说出重点,请大家补充,如果大家有什么更好的答案请拿出来一起分享

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值