• spring入门aop和ioc


    spring分层架构

    1. 表现层

      springmvc

    2. 服务层(业务层)

      spring ioc

    3. 持久层

      mybatis

      mybatis plus

      hibernite

    互联网项目,多ssm结构

    spring核心

    1. ioc(控制反转)

      ioc将对象的创建权利交给spring框架,底层实际上是使用反射实现的。降低程序的耦合度

      1)接下来是代码示例:
      1. 创建一个空的maven项目

      2. 引入一些基本依赖

      <dependencies>
              <dependency>
                  <groupId>org.springframeworkgroupId>
                  <artifactId>spring-contextartifactId>
                  <version>5.0.2.RELEASEversion>
              dependency>
              <dependency>
                  <groupId>commons-logginggroupId>
                  <artifactId>commons-loggingartifactId>
                  <version>1.2version>
              dependency>
              <dependency>
                  <groupId>log4jgroupId>
                  <artifactId>log4jartifactId>
                  <version>1.2.12version>
              dependency>
              <dependency>
                  <groupId>junitgroupId>
                  <artifactId>junitartifactId>
                  <version>4.12version>
                  <scope>testscope>
              dependency>
      
          dependencies>
      
      1. 准备实体类

        // 创建一个接口
        public interface UserService {
            public void hello();
        }
        // 创建一个实体类
        public class UserServiceImpl implements UserService {
            @Override
            public void hello() {
                System.out.println("Hello, world!");
            }
        }
        
        
      2. 准备配置文件

        
        <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
        http://www.springframework.org/schema/beans/spring-beans.xsd">
            <bean id="us" class="实体类的路径">bean>
        beans>
        
      3. 在test中测试

        // 常规方法
            @Test
            public void testUser() {
                // TODO: write test cases for UserService
                UserService userService = new UserServiceImpl();
                userService.hello();
            }
        // 基于ioc容器管理的方法,ioc是一个map key是对象的标识,value是ioc创建的对象
            @Test
            public void run1() {
                // 创建spring ioc工厂
                ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
                // 获取bean
                UserService userService = (UserService) ac.getBean("us");
                userService.hello();
            }
        

      上面就是一个关于ioc容器的示例

      2)ioc容器的使用过程

      ApplicationContext接口,这个工厂接口,使用这个接口就可以获得相应的Bean对象,该对象下有两个实现类

      1. ClassPathXmlApplicationContext:加载类路径下的spring配置文件(常用)
      2. FileSystemXmlApplicationContext:加载本地磁盘下的spring配置文件(让项目和配置文件分离管理,不常用)
      3)ioc中的bean管理
      1. id属性:bean的别名,取名要求:必须要字母开头,可以使用数字,连字符,下划线,字母,不能出现特殊字符
      2. class属性:bean对象的全路径
      3. scope属性: bean对象的作用范围
        1. singleton:单例(默认)生命周期和配置文件一样
        2. prototype:多例,不是加载配置文件时创建,而是在获取实例对象时创建
        3. request: 多例,不常用,应用于web项目中,每个请求都会创建一个新的实例对象
        4. session:多例,不常用,应用于web项目中,向一个http session中共享一个实例
      4. init-method:bean对象创建时可以配置一个指定的方法自动调用
      5. destory-method:bean对象销毁时可以配置一个指定的方并自动调用
      4)实例化bean的三种方式
      1. 默认是无参的构造方法

            <bean id="us" class="实体类的路径">bean>
        
      2. 静态工厂实例化方法(好处是可以自己编写业务逻辑)

        准备一个静态工厂类

        public class StaticFactory {
            public static UserService createUser() {
                // 编写业务逻辑
                // ......
                return new UserServiceImpl();
            }
        }
        

        在xml配置文件中使用

            <bean id="us1" class="com.qc.util.StaticFactory" factory-method="createUser">bean>
        
      3. 实例化工厂实例化方式

        准备一个可以实例化的类

        public class DFactory {
            public  UserService createUser() {
                // 编写业务逻辑
                return new UserServiceImpl();
            }
        }
        

        在xml配置文件中使用

            <bean id="factory" class="com.qc.util.DFactory">bean>
            <bean id="us2" factory-bean="factory" factory-method="createUser">bean>
        
    2. aop(面向切面开发)

      定义

      是一种编辑的范式,是OOP的延续,也是Spring框架中函数编程的一种衍生范式,利用AOP可以对业务的各个部分进行隔离,从而似的业务逻辑各部分之间的耦合度降低,提高了程序的重用性,同时提高了开发的效率,AOP采用横向抽取机制,取代了传统纵向继承体系。

      优势

      1. 运行期间,不修改源代码的情况下,对已有的方法进行增强,减少重复代码
      2. 提高开发效率
      3. 方便维护

      AOP底层原理

      1. 如果使用接口,则使用JDK动态代理技术,如果没有使用接口,使用的是继承则是cglib代理

      AOP相关的术语

      1. Joinpoint(连接点)所谓连接点是指那些被连接到的点,在spring中,这些带点指的是方法,因为spring只支持方法类型的节点
      2. Pointcut(切入点)所谓切入点是我们要对哪些Joinpoint进行拦截的定义
      3. Advice(通知\通知)所谓通知就是指,拦截到Joinpoint之后所要做的情况就就是通知,通知分为,前置通知,后置通知,异常通知,最终通知,环绕通知(切面类中要完成的功能)
      4. Target(目标对象)代理的目标对象
      5. Weaving(织入)是指把增强应用到目标对象来创建新的代理对象的过程
      6. Proxy(代理)一个类被AOP织入增强后,就产生一个结果代理类
      7. Aspect(切面)是切入点+通知的结合,是自己编写和配置

      AOP入门

      1. 导入坐标依赖

        
                    aopalliance
                    aopalliance
                    1.0
                
                
                
                    org.springframework
                    spring-aspects
                    5.0.2.RELEASE
                
                
                
                    org.aspectj
                    aspectjweaver
                    1.8.3
                
        
        
        
        
        
      2. 编写spirng配置文件中AOP的配置部分

            
            
            
        
            
            
                
                
                    
                    
                    
                    
                    
                    
                    
                    
        
                    
                    
                
            
        
        import org.aspectj.lang.ProceedingJoinPoint;
        
        public class MyAspect {
            // 自定义切面类 = 切入点+通知
            //通知
            public void log1() {
                System.out.println("前置增强的");
            }
        
            public void log2() {
                System.out.println("后置增强的");
            }
        
            public void log3() {
                System.out.println("异常增强的");
            }
        
            public void log4() {
                System.out.println("最终增强的");
            }
        
        
            public void aroundLog(ProceedingJoinPoint point) {
                try {
                    log1();
                    point.proceed(); // 目标方法调用
                    log2();
                } catch (Throwable e) {
                    e.printStackTrace();
                    log3();
                } finally {
                    log4();
                }
            }
        }
        

        注意环绕通知使用的接口

      通知类型

      1. 前置通知:目标方法执行前进行增强
      2. 后置通知:目标方法执行后进行增强
      3. 异常通知:目标方法出现异常后进行增强
      4. 最终通知:目标方法无论是否异常都进行增强
      5. 环绕通知:目标方法执行前后,都进行增强,不过需要自己书写

      切入点表达式

      • execution([修饰符] 返回值 包名.类名.方法名(参数))
      • 修饰符可以省略不写
      • 返回值类型不能省略,根据方法来编写返回值,可以用星号来代替
      • 包名类型方法名是不能省略的,但是可以用星号来代替,也可以部分代替
      • 参数如果是一个可以用星号来代替,如果是多个可以使用两个点

      因此比较通用的表达式:

      execution( com.qc.*.Service.save(…))

      aop注解开发

      给切面添加@Aspect,编写增强的方法,使用通知类型注解声明

          
          <context:component-scan base-package="com.qc"/>
      
          
          <aop:aspectj-autoproxy/>
      
      @Aspect
      @Component
      public class MyAspect {
          // 自定义切面类 = 切入点+通知
          //通知
          @Before("execution(* com.qc.*.*.*ServiceImpl.save(..))")
          public void log1() {
              System.out.println("前置增强的");
          }
      
          @AfterReturning("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
          public void log2() {
              System.out.println("后置增强的");
          }
      
          @AfterThrowing("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
          public void log3() {
              System.out.println("异常增强的");
          }
      
          @After("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
          public void log4() {
              System.out.println("最终增强的");
          }
      
          @Around("execution(* com.qc.*.*.*ServiceImpl.save*(..))")
          public void aroundLog(ProceedingJoinPoint point) {
              try {
                  log1();
                  point.proceed(); // 目标方法调用
                  log2();
              } catch (Throwable e) {
                  e.printStackTrace();
                  log3();
              } finally {
                  log4();
              }
          }
      }
      

      在每个方法上使用注解进行配置,和配置文件类似

      通知类型注解:

      1. @Before 前置注解
      2. @AfterReturning 后置注解
      3. @AfterThrowing 异常注解
      4. @After 最终注解
      5. @Round 环绕注解

      注意:在配置文件中开启自动代理

      aop纯注解开发

      @EnableAspectJAutoProxy 开启自动代理

    3. Di(依赖注入)

      依赖注入:在spring框架负责创建bean对象时,动态的将对象注入到其他的bean对象中

      1)属性的set方法注入值的方式
      1. 声明变量并在需要依赖注入的地方设置set方法

      2. 在xml文件中配置该变量的值

            <bean id="us" class="com.qc.service.impl.UserServiceImpl">
                <property name="userDao" ref="">property>
                <property name="name" value="">property>
            bean>
        

        参数说明:如果property中的是一个简单类型(基本类型和字符串),那么就使用value,否则就使用ref

      2)构造方法赋值的方法
      1. 在需要的地方添加构造方法

      2. 在配置文件中使用带参数的构造方法传参

            <bean id="userDao" class="com.qc.dao.impl.UserDaoImpl">bean>
            <bean id="us" class="com.qc.service.impl.UserServiceImpl">
                <constructor-arg name="userDao" ref="userDao">constructor-arg>
            bean>
        
      3. 其他类型的参数传参

        准备一个java类

        public class CollectionBean {
            private String[] strs;
            private List<String> list;
            private Map<String, String> map;
            private Properties properties;
        
            public Properties getProperties() {
                return properties;
            }
        
            public void setProperties(Properties properties) {
                this.properties = properties;
            }
        
            public Map<String, String> getMap() {
                return map;
            }
        
            public void setMap(Map<String, String> map) {
                this.map = map;
            }
        
            public String[] getStrs() {
                return strs;
            }
        
            public List<String> getList() {
                return list;
            }
        
            public void setList(List<String> list) {
                this.list = list;
            }
        
            public CollectionBean() {
            }
        
            public void setStrs(String[] strs) {
                this.strs = strs;
            }
        
            public CollectionBean(String[] strs) {
                this.strs = strs;
            }
        }
        
        1. 不可变数组

          <bean id="co" class="com.qc.service.CollectionBean">
                  <property name="strs">
                      <array>
                          <value>小美value>
                          <value>小张value>
                          <value>小王value>
                      array>
                  property>
              bean>
          
        2. 可变集合

              <bean id="co" class="com.qc.service.CollectionBean">
                  <property name="list">
                      <list>
                          <value>张三value>
                          <value>李四value>
                          <value>王五value>
                      list>
                  property>
              bean>
          
        3. map集合

          <bean id="co" class="com.qc.service.CollectionBean">
                  <property name="map">
                      <map>
                          <entry key="name" value="zhangsan">entry>
                          <entry key="age" value="18">entry>
                      map>
                  property>
              bean>
          
        4. 其他类型

            <bean id="co" class="com.qc.service.CollectionBean">
                  <property name="properties">
                      <props>
                          <prop key="username">zhangsanprop>
                          <prop key="password">1234prop>
                      props>
                  property>
              bean>
          
    4. 多配置文件

      1. 在配置文件中使用

        <import resource="applicationContext.xml">import>
        
      2. 创建工厂时直接加载多个配置文件

                ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext1.xml");
        

                    
                         zhangsan
                         1234
                     
                 
             
         ```
    
    1. 多配置文件

      1. 在配置文件中使用

        <import resource="applicationContext.xml">import>
        
      2. 创建工厂时直接加载多个配置文件

                ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext1.xml");
        

  • 相关阅读:
    凭借32量子比特!Rigetti Computing打入英国量子计算市场
    Mybatis对数据库进行增删查改以及单元测试
    谈谈我对服务网格的理解
    mysql安装8.0详细操作
    1017 Queueing at Bank
    .NET服务治理之限流中间件-FireflySoft.RateLimit
    bootstrap_study
    LeetCode 210:课程表 II (拓扑排序)
    Flink docker-compose 单机版 安装教程
    java设计模式---代理模式详解
  • 原文地址:https://blog.csdn.net/NiNg_1_234/article/details/139470820