• Spring5复习IOC与AOP


    1.AOP:控制反转,把创建对象的过程交给Spring容器

    2.IOC:面向切面编程,不改源代码进行功能增强

    bean.xml文件

    <bean id = "昵称" class = "类的全类名" ></bean>

    测试 

    1.加载spring配置文件
    ApplicationContext  context  = new ClassPathXmlApplicationContext("bean.xml");//src下的可以直接这样扫描
    2.得到配置的对象
      类名 昵称= context.getBean("bean中ID",类名.class);
    
    3.调用bean中对象类中的方法
      昵称.method();

    IOC容器:

    (1)IOC底层原理

    (2)IOC接口(BeanFactory)

    (3)IOC操作Bean管理(注解与xml)

     控制反转-->对象的创建与对象调度都交给spring管理

    (1):...

    ------> 原始模式(耦合度高)

     ------>工厂模式

     ------>IOC过程

    IOC(接口)

    IOC思想基于IOC容器,底层是对象工厂

     Spring提供IOC容器实现的两种方式(两个接口)加载配置文件,获取配置创建对象

    (1)BeanFactory:spring内置接口,不提供给开发人员使用。

    加载配置文件时 不创建对象,获取(使用)对象的时候才会创建对象----getBean("");

    (2)ApplicationContext:上面的子接口,功能更强,开发人员使用

    加载即创建。

    (3)ApplicationContext接口的实现类

     IOC操作Bean管理

    (1)xml

    (2)注解

    创建对象时默认执行无参构造方法 

    xml方式注入属性:

    (1)DI:依赖注入(ioc的一种具体实现)

        1. set方法注入:

    //在类中生成set方法

    <bean id = "" class =""> <!-- name:类中属性名称 value:向属性中注入的值 --> <property name = "" value =""></property> </bean>

        2. 有参注入:

    //在类中生成有参构造方法

    <bean id ="" class = ""> <constructor-arg name = "" value =""> </contructor-arg> </bean>

        p 名称空间注入

    (1)用于简化xml配置

       

      //添加p名称空间
      xmlns:p="http://www.springframework.org/schema/p"
      //set注入属性
      <bean id = "" class = "" p:属性名 = "属性值" >
     
     </bean>

    xml注入其他类型:

    null<property name ="">
        <null/>
      </property>
    
    
    特殊符号:
        <property name ="" >
        <value>
         < <![CDATA[****]]>>
    
         </value>
         </property>

    注入属性-外部bean

    (1)创建两个类  service 和 mapper

    (2) service 调用 mapper 

     

     <!-- ref 就是将外部的bean注入进来-->

     注入属性-内部bean和级联赋值

    (1)一对多

    (2)实体类中表示一对多关系

    <!-- emp 对象-->
    <bean id = "emp" class = "">
    <!-- emp的属性和dept对象属性--> <property name = "" value = ""> </property> <property name = "dept" > <bean id = "dept" class = "">
    <property name = "" value = ""></property>
    </bean> <property>
    </bean>

    ---------------------------------------------------内部bean

    注入属性-级联赋值1

    <!-- emp 对象-->
    <bean id  = "emp" class = "">
    <!-- emp的属性和dept对象属性-->
        <property name = "" value = ""> </property>
        <property name = "dept" ref = "dept"></property>
    <!--外部bean 级联赋值-->
    </bean>
            <bean id = "dept" class = "">
                  <property name  = "" value = ""><property>
     </bean>

    注入属性-级联赋值2(猜测比外部级联优先级高)

    <!-- emp 对象 生成一下getDept方法-->
    <bean id  = "emp" class = "">
    <!-- emp的属性和dept对象属性-->
        <property name = "" value = ""> </property>
        <property name = "dept" ref = "dept"></property>
         <property name = "dept.dname" value= ""></property>
    <!--外部bean 级联赋值-->
    </bean>
            <bean id = "dept" class = "">
                  <property name  = "" value = ""><property>
     </bean>

    xml注入集合属性:

    <!-- 数组-->
    <bean ...>
        <property name = "course">
         <array>
            <value>...</value>
                     ......
            </array>
        </property>     
    
    <!-- map -->
    
        <property name = "maps">
         <map>
            <entry key = "" value = ""> </entry>
                     ......
            </map>
        </property>     
    
    <!-- list-->
    
        <property name = "list">
         <list>
            <value>...</value>
                     ......
            </list>
        </property>     
    
    <!-- set-->
    
        <property name = "list">
         <set>
            <value>...</value>
                     ......
            </set>
        </property>     

     注入集合对象2

     

    <!-- 注入list集合类型 ,值是对象-->
    <property name = "courseList">
              <list>
               <ref bean = "" ></ref>
               </list>
      </property>
    
    
    <!--创建多个course对象-->
    <bean 1>
    <property/>
    ....
    <bean 2>
    <property/>
    ....

    把集合注入部分提取出来:

    引入名称空间util

    <util:list id = "bookList">
        <value></value>
        <value></value>
    </util:list>
    
    
    
    <bean id  = "book " class = "">
       <property name = '"'  ref = "bookList"></>
    </>

     IOC操作bean管理(FactoryBean)

    1. 普通bean

    2.FactoryBean (定义bean类型与返回类型可以不同)

    第一步 :创建类 ,作为工厂bean ,实现FactoryBean 。

    第二步 :实现接口里面的方法,在实现方法中定义返回的bean类型

    public class MyBean implements FactoryBean<Course>{
           //定义返回Bean
           public Course getObject () throws Exception{
                        new Course();-->course
                                course.setCname("....");
                                      return course;
          }
              public Class<?> getObjectType() {
                   return null;
    
               }
             public boolean isSingleton () {
                         return false;
             
        }
               
    
    }
    --------------------------------------------------------------------
    <bean id = "myBean" class = ""></bean>
    .....
    
    context.getBean("myBean", Course.class); --->course

    bean的作用域:

    通过scope属性的值来设置:

    scope = "singleton"(默认)  加载配置文件时就会创建单实例对象

    prototype:多实例  调用getBean方法时创建多实例对象

    request:一次请求

    session:一次会话

    bean的生命周期:

    (1)无参构造创建bean实例

    (2)为bean的属性设置值,对其他bean的引入(调用set方法)

    (3)把bean实例传递给bean后置处理器postProcessBeforeInitialization方法

    (3)调用bean的初始化的方法

    (4)把bean实例传递给bean后置处理器postProcessAfterInitialization方法

    (4)使用bean

    (5)容器关闭时,调用bean的销毁方法。

    //在类中创建初始化方法 init () 和 销毁方法 destroy()
    <bean id  =  "" class  = "" init-method = "init " destroy-method = "destroy"> 
    <property></>
    </bean>
    ..........
    contex.close();
    ApplicationContext接口中没有close方法
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ();

    添加后置处理器:

    (1)创建类 MyBeanPost,实现BeanPostProcessor接口

    (2)实现其中两个方法

    <!-- 配置后置处理器  为配置文件中所有bean实例创建后置处理器-->
    <bean id  = "myBeanPost" class = "....MyBeanPost">

    xml自动装配:

    根据指定装配规则(属性名称 属性类型),Spring指定将匹配的属性值进行注入

    autowire = "byName";byType;

    byName 注入值bean得id值与类的属性名称一致

    外部属性文件:

    1.创建外部属性文件

    2. 在配置文件中添加context命名空间

    <!-- 引入外部文件-->
    <context:property-placeholder location ="classpath:jdbc.properties" >
    <!-- 配置连接池-->
    <bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
      <property name = "driverClassName" value"${prop.driverClass}"></property>
    .....
    </bean>

    IOC注解

    Spring针对bean管理中创建对象提供的注解:

    (1)@Component

    (2)@Service

    (3)@Controller

    (4)@Repository

    基于注解实现对象创建

    第一步  引入依赖

    第二步  开启组件扫描<context>

    多个包之间 逗号隔开(扫描上层目录也行)

    <context:component-scan base-package = " "></context:component-scan>

    第三步 创建类 在类上添加注解

    //自定义配置filter
    <context : component-scan base-package = "" use-default-filters = "false">
    <context : include-filter type = "annotation" expression = "org.springframework.stereotype.Controller"/>
    </>
    exclude-filter type 不扫描哪些内容

    注解实现属性注入:

    (1)@AutoWired :根据属性类型注入

    (2)@Qualifier:根据属性名称注入

    根据类型注入,一个借口可能有多个实现类,可以在AutoWired 下添加Qualifier(value ="userDaoImpl1")

    (3)@Resource:都行

    如果要根据名称注入 Resource(name = "")

    (4)@Value:注入普通类型属性

        为定义的属性赋值

    service中定义dao类型属性,是由于spring的设计思想是利用java的多态特性 减少耦合

    完全注解开发:

    配置类:SpringConfig

    @Configuration

    @Component(basePackages ={""})

     SpringConfig

    加载配置类

    new AnnotationConfigApplicationContext(SpringConfig.class);-->ApplicationContext

    AOP(底层动态代理)

    不改源代码,增加新功能

    动态代理:

    (1)有接口:创建接口实现类代理对象,增强类方法

    (2)没有接口:创建类的子类代理对象

    1.JDK动态代理,使用Proxy类里面的方法创建代理对象

    调用nexProxyInstance方法

     参数一:类加载器

     参数二:增强方法所在的类,这个类实现的接口,支持多个接口

     参数三:实现这个接口InvocationHandler,创建代理对象,写增强部分的代码

    public class JDKProxy{
       psvm{
    <!-- 创建接口实现类代理对象-->
                Class [] interfaces = {UserDao.class};
    UserDaoImpl userDao = new UserDaoImpl();
          Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new InvocationHandler(){
    public Object invoke (Object proxy,Method method,Object[] args) throws Throwable{
         return null;
    }
    }
    );
    -------------------------------------------------------------------------
    UserDao dao 
    =Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDapProxy(userDao) );
    
    
    
    
        }
    }
    
    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler{
    //把创建的是谁的代理对象,就把谁传递过来
    //有参构造传递
      private Object obj;
     public UserDaoProxy(Oject obj){
        this.obj = obj;   
    }
    
    
    
      public Object invoke (Object proxy,Method method,Object[] args) throws Throwable{
      
       Onject  res  =  method.invoke(obj,args);
         return res;
    }
    }

    Aop(术语)

    1.连接点:可以被增强的方法

    2.切入点:实际被增强的方法

    3.通知(增强):增加的部分逻辑

        前置通知  后置通知  环绕通知  异常通知  最终通知

    4.切面

      把通知应用到切入点的过程

    基于AspectJ实现AOP操作

    独立的AOP框架

    切入点表达式

    作用:知道哪个类里面的哪个方法进行增强

    execution([权限修饰符] [返回类型][全类名][方法名称]([参数列表]))

    AspectJ注解

    (1)xml中添加context,aop命名空间,开启注解扫描

    (2)使用注解创建User和UserProxy对象

    (3)增强类上加注解@Aspect 生成代理对象

    (4)开启Aspect生成代理对象

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    @Component
    @Aspect
    public class UserProxy{
    //前置通知 @Before(value
    = "execution(*org.xxx.User.add(..))") public void before(){ System.out.println("...."); } }
    @After(value = "")最终通知
    @AfterReturning(value = "")后置通知 (返回通知)有异常不执行
    @Around(value = "")环绕通知 参数为 ProceedingJoinPoint proceedingJoinPoint
    sout 前
    proceedingJoinPoint.proceed();
    sout 后
    @AfterThrowing(value = "")异常通知

     抽取相同的切入点

    @Pointcut(value = "execution(*org.xxx.User.add(..))")

    public void pointdemo(){

    }

    @Before (value = "pointdemo()")

    多个增强类对一个方法进行增强:优先级

    增强类上加一个注解@Order(数值类型放入值)值小优先级高

    配置文件做AspectJ

    <!-- 配置AOP增强-->
     <aop:config>
        <!-- 切入点-->
          <aop:pointcut id = "p" expression = "execution(*org.xxx.Book.Buy(..))"/>
       <!-- 配置切面-->
    <aop :aspect ref = "bookProxy">
      <!--增强作用在具体的方法上-->
      <aop:before method = "before"  pointcut-ref = "p" >
     </aop:aspect>
    </aop:config>
    
    <bean id ="book" class = ""></>
    <bean id  ="bookProxy" class = "">

    @EnableAspectJAutoProxy(proxyTargetClass = true)

  • 相关阅读:
    TypeError: can't compare offset-naive and offset-aware datetimes bugfix
    pg_restore数据库恢复指令
    第四十期百度技术沙龙笔记整理
    JS事件模型小结
    matlab Newton method
    Markdown 语法的简要规则
    iOS社交分享Twitter、Facebook、拷贝到剪切板、LINE、及邮件
    Linux系统调用过程分析
    iOS自己定义返回button(不影响返回手势)
    MAVEN项目模块化
  • 原文地址:https://www.cnblogs.com/smallores/p/13520390.html
Copyright © 2020-2023  润新知