暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring核心之一:IoC

咱们码码人儿 2021-08-19
254

IOC

IoC(inversion of Controller) 控制反转

主动式:  通过创建对象,创建对象使用的时候使用new的方式进行

被动式:  资源的获取不是通过人进行设置,而是交给一个容器设置

第一个Spring程序

  1. 需要导入spring的5个核心jar包和一个日志commons-login

  2. 编写实体类

     //创建实体类
    public class User {
    private String name;
    private Integer age;
    private String sex;
    }
    1. 编写配置文件

      <!-- 创建配置文件名称为applicationContext.xml -->
      <bean id="user" class="com.xztx.entity.User">
      <property name="name" value="smith"></property>
      <property name="age" value="20"></property>
      <property name="sex" value="女"></property>
      </bean>
      1. 测试

         public class Test{
        private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        public static void main(String[] args){
        test01();
        }
        public static void test01(){
        User user = context.getBean("user",User.class);//这里使用了反射可以不让对象进行强制转换
        System.out.println(user);
        }
        }

        DI

        DI(dependency injection) 依赖注入

        DI是IoC的一个实现方式

        注入的方式通常有两种: set方式注入和将要学习的通过配置文件方式进行注入

           //把配置文件放在src下边
          ApplicationContext context = new ClassPathXmlApplicationContext("类路径下");
          //如果不想把配置文件放在src下边
          ApplicationContext context = new FileSystemApplicationContext("系统目录下");

          获取配置文件的几种方式

            context.getBean("传入唯一值");//通过id值
            context.getBean("传入实体类的类名.class")//通过类型获取
            context.getBean("要查找的唯一值",查找的类型.class);//通过类型查找
            context.getBean();//通过构造器

            配置文件可以创建多个对象,创建的所有对象在获取容器的时候都会被实例化

             
              <bean id="user1" class="com.xztx.entity.User">
              <property name="name" value="jack"></property>
              ...<!-- 这是第一个赋值的对象 -->
              </bean>
              <bean id="user1" class="com.xztx.entity.User">
              <property name="name" value="jack"></property>
              ...<!-- 这是第二个赋值的对象 -->
              </bean>
                public class Test{
                private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                public static void main(String[] args){
                test01();
                }
                public static void test01(){
                //这里只是获取到user1中的值,但是程序在运行的时候虽然没有显示user2的值,但是这个对象依然被创建了
                User user = context.getBean("user1",User.class);
                System.out.println(user);
                }
                }

                配置文件给属性赋值的方式

                  <!-- 通过property给属性赋值 -->
                  <!-- 赋值的时候如果属性是基本数据类型使用value赋值,如果是对象类型使用ref进行赋值 -->
                  <bean parent="这个的id" abstract="true"><!-- 使用parent继承这个类的配置信息,abstract不能被实例,只能被继承 -->

                  <property name="" value=""></property>
                  <property name="">
                  <!-- 使用内部bean -->
                  <bean class="">
                  <property name="" value=""></property>
                  </bean>
                  </property>


                  <!-- 通过构造器给属性赋值 -->
                  <constructor-arg name="" value="jack"></constructor-arg>
                  <!-- 通过构造器索引惊醒赋值,索引从0开始 -->
                  <constructor-arg value="" index="0"></constructor-arg>
                  <!-- 通过类型进行赋值 -->
                  <constructor-arg value="" type="String"></constructor-arg>
                  </bean>

                  工厂模式给对象赋值

                  静态工厂
                    <!-- 静态工厂模式 -->
                    <!-- factory-method:指定静态工厂实现的方法名称 -->
                    <bean id="" class="使用工厂的全类名" factory-method="" >
                    <!-- 如果工厂类的方法里边有参数需要设置参数 -->
                    <constructor-arg value=""></constructor-arg>
                    </bean>

                    就是工厂本身创建对象,工厂类名.工厂方法名

                    1. 实体类

                      public class Dog {
                      private String name;
                      private Integer id;
                      private Integer age;
                      public Integer getAge() {
                      return age;
                      }
                      public void setAge(Integer age) {
                      this.age = age;
                      }
                      public String getName() {
                      return name;
                      }
                      public void setName(String name) {
                      this.name = name;
                      }
                      public Integer getId() {
                      return id;
                      }
                      public void setId(Integer id) {
                      this.id = id;
                      }
                      }
                      1. 创建静态工厂 staticFactory

                         public class StaticFactory {
                        public User getDog(String name){
                        Dog dog = new Dog();
                        dog.setId(1);
                        dog.setAge(3);
                        return dog;
                        }
                        }
                        1. 编写配置文件

                          <bean id="dog" class="com.wyxz.factory.StaticFactory" factory-method="getUser">
                          <constructor-arg value="大黄"></constructor-arg>
                          </bean>
                          1. 测试文件省略

                          实例工厂

                          工厂本身需要创建对象 工厂 = new 工厂().工厂方法名()

                          实例工厂 InstanceFactory = new InstanceFactory ().getUser();

                            <!-- 实例工厂模式 -->
                            <!--
                            class 指定的是实体类的全类名
                            factory-method 指定使用哪个工厂方法
                            factory-bean 指定使用哪个工厂实例
                            -->
                            <bean id="" class="使用本类的全类名" factory-method="" factory-bean="">
                            </bean>
                            1. 实体类不变

                            1. 编写工厂类

                               public class InstanceFactory {
                              public User getDog(String name){
                              Dog dog = new Dog();
                              dog.setId(1);
                              dog.setAge(3);
                              return dog;
                              }
                              }

                              3. 配置文件

                                <bean id="isntanceFactory" class="com.wyxz.entity.Dog" factory-method="getDog" factory-bean="InstanceFactory">
                                </bean>
                                1. 测试省略

                                factory-bean

                                factory-bean 是spring的一个接口,如果要是实现了这个接口,spring都会认为是一个工厂类

                                  //可以实现一个Factory 创建一个工厂对象
                                  public class MyFactory implements FactoryBean<Dog> {
                                  /**
                                  1. getObject()方法,返回对象的创建
                                  User user = new User();
                                  */
                                  @Override
                                  public Dog getObject() throws Exception {
                                  return null;
                                  }
                                  /**
                                  2. getObjectType()方法,返回创建的对象的类型
                                  */
                                  @Override
                                  public Class<?> getObjectType() {
                                  return null;
                                  }
                                  /**
                                  3. isSingleton()方法,是否是单例
                                  return true/false;
                                  */
                                  @Override
                                  public boolean isSingleton() {
                                  return false;
                                  }
                                  }

                                  工厂创建好之后怎样让spring识别这个类呢,需要在配置文件中如下配置:

                                    <bean id="myFactory" class="com.xztx.factory.MyFactory" >
                                    </bean>

                                    bean的生命周期

                                    1. 创建实体类

                                      public class Dog {
                                      private String name;
                                      private Integer id;
                                      private Integer age;
                                      public Integer getAge() {
                                      return age;
                                      }
                                      public void setAge(Integer age) {
                                      this.age = age;
                                      }
                                      public String getName() {
                                      return name;
                                      }
                                      public void setName(String name) {
                                      this.name = name;
                                      }
                                      public Integer getId() {
                                      return id;
                                      }
                                      public void setId(Integer id) {
                                      this.id = id;
                                      }
                                      }
                                      1. 再配置文件中设置生命周期

                                        <!-- 注意 注意 生命周期方法可以抛异常,但是方法一定不能有参数 -->
                                        <bean id="dog" class="com.wyxz.entity.Dog" init-method="init" destory-method="destory"></bean>

                                        bean的后置处理器

                                        bean的后置处理器是spring的一个接口,可以在bean的初始化前后调用方法,需要实现BeanPostProcessor接口

                                          public class MyAfter implements BeanPostProcessor {
                                          //实现相关方法
                                          /**
                                          postProcessBeforeInitialization() 初始化方法之前调用

                                          */
                                          @Override
                                          public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
                                          System.out.println( s + "方法被调用,名字是" + o);
                                          return o;
                                          }
                                          /**
                                          postProcessorAfterInitialization() 初始化方法之后调用
                                          */
                                          @Override
                                          public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
                                          System.out.println( s + "方法被调用,名字是" + o);
                                          return null;
                                          }
                                          }

                                          在配置文件中注册

                                            <bean id="myAfter" class="com.xztx.controller.MyAfter" ></bean>

                                            spring连接池

                                            编写连接数据库的基本配置(外部配置)

                                              user=root
                                              password=123456
                                              jdbcUrl=jdbc:mysql://localhost:3306/test
                                              driverClass=com.mysql.jdbc.Driver

                                              使用xml文件读取配置文件信息

                                                <!-- 对配置文件进行扫描,读取配置文件 -->
                                                <context:property-placeholder location="classpath:配置文件名.properties"/>
                                                <bean id="dataSource" class="要连接的连接池的全类名">
                                                <!-- 获取配置文件中的信息 -->
                                                <property name="name" value="${name}"></property>
                                                <property name="password" value="${password}"></property>
                                                <property name="jdbcrUrl" value="${driverUrl}"></property>
                                                <property name="driverClass" value="${driverClass}"></property>
                                                </bean>
                                                  public class TestConnection {
                                                  public static void main(String[] args){
                                                  ApplicationContext context = new ClassPathXmlApplicationContext("jdbc.xml");
                                                  Connection connect = context.getBean("dataSource");
                                                  System.out.println(connect);
                                                  }
                                                  }

                                                  自动装配

                                                  在bean中添加属性 autowired进行自动装配

                                                    <!-- 使用autowired为属性自动赋值 -->
                                                    <bean id="dog" class="com.wyxz.entity.Dog" autowired="default"></bean>
                                                      public class Dog {
                                                      private String name;
                                                      private Integer id;
                                                      private Integer age;
                                                      public Integer getAge() {
                                                      return age;
                                                      }
                                                      public void setAge(Integer age) {
                                                      this.age = age;
                                                      }
                                                      public String getName() {
                                                      return name;
                                                      }
                                                      public void setName(String name) {
                                                      this.name = name;
                                                      }
                                                      public Integer getId() {
                                                      return id;
                                                      }
                                                      public void setId(Integer id) {
                                                      this.id = id;
                                                      }
                                                      }


                                                      spring注解声明及配置

                                                      @Service : 给service添加的注解

                                                      @Controller: 给servlet的组件添加的注解

                                                      @reponsity: 给数据层(dao层)的组件添加的注解

                                                      @Component:给不是以上几层的组件添加的注解

                                                        @Controller
                                                        public class UserServlet{}
                                                        @Reponsity
                                                        public class UserDao{}
                                                        @Service
                                                        public class UserService{}

                                                        那么在类上声明完之后如何让spring识别呢?

                                                        在配置文件中加入如下配置

                                                          <!-- 通过spring的扫描器扫描加了注解的类,要扫描的基础包的类名,比如这个就是扫描com.xztx下边的所有子包和文件 -->
                                                          <context:component-scan base-package="com.wyxz" >

                                                          Autowired注解实现自动装配

                                                          使用@Autowired进行装配,如果找到了就自动装配,如果没有找到就报错,可以使用@Qualifier指定一个新的id值,如果找到了继续装配,如果没有找到报错,可以给autowired添加一个属性require属性设置true或者false

                                                          和@Autowired注解相同的注解还有@Resource注解

                                                          都是自动装配,但是@Resource没有@Autowired强大,因为Autowired是spring提供的,而Resource是java提供的,Resource扩展性更强大

                                                            <!-- 要扫描的基础包的类名,比如这个就是扫描com.xztx下边的所有子包和文件,需要在配置文件加入此配置 -->
                                                            <context:component-scan base-package="com.wyxz" >
                                                              public class UserDao{

                                                              }
                                                              public class UserService
                                                              private UserDao userDao;

                                                              public void save(){
                                                              System.out.println("调用suerDao保存数据");
                                                              }
                                                              }

                                                              public class UserServlet {
                                                              @AutoWired() //自动的为userService赋值,不使用new的方式
                                                              private UserService userService;

                                                              public void do(){
                                                              System.out.println("将信息传递给userService保存");
                                                              userService.save();
                                                              }
                                                              }
                                                                public class Test{
                                                                private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                                                                public static void main(String[] args){
                                                                test01();
                                                                }
                                                                public static void test01(){
                                                                //这里只是获取到user1中的值,但是程序在运行的时候虽然没有显示user2的值,但是这个对象依然被创建了
                                                                UserServlet userServlet = context.getBean("userServlet",UserServlet.class);
                                                                userServlet.do();//调用userServlet的do方法
                                                                }
                                                                }


                                                                Spring单元测试

                                                                spring-test的单元测试包

                                                                @ContextConfiguration(location="xml文件") 指定spring的配置文件位置

                                                                @RunWith()  可以指定需要使用驱动进行单元测试,默认使用的是JUnit进行测试

                                                                导入spring-test的包

                                                                  @ContextConfiguration(location="applicationContext.xml")
                                                                  @RunWith(SpringJUnit4ClassRunner.class)//指定单元测试框架使用类型,需要使用反射获取测试类的类型
                                                                  public class Test {

                                                                  //private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
                                                                  @Autowired
                                                                  UserServlet userServlet;
                                                                  public static void main(String[] args){

                                                                  }
                                                                  }

                                                                  面试题

                                                                  BeanFactory和ApplicationContext的区别?

                                                                  • ApplicationContext是BeanFactory的子接口

                                                                  • BeanFactory bean是工厂接口,负责创建bean实例

                                                                  • ApplicationContext是容器接口,更多的负责容器红能的实现,容器可以从map中获取bean,并且aop,di在applicationContext接口的这些类里面

                                                                  • beanFactory最底层的接口,applicationContext是使用的接口




                                                                  文章转载自咱们码码人儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                                  评论