zoukankan      html  css  js  c++  java
  • spring IOC与AOP

    Spring IOC容器

    spring IOC 容器有两种,分别是 BeanFactory 容器和 ApplicationContext 容器。

    BeanFactory如下:

    /*第一步,利用ClassPathResource()API加载路径CLASSPATH下的可用的Bean的xml配置文件
      然后利用框架提供的 XmlBeanFactory() API生成工厂Bean,XmlBeanFactory()负责创建和初始化所有对象
      然后用getBean方法得到所需要Bean并转化类型为真正的对象
    */
    XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));   
    HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
    obj.getMessage();
    <?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
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
       <bean id="helloWorld" class="com.tutorialspoint.HelloWorld">
           <property name="message" value="Hello World!"/>
       </bean>
    
    </beans>

    ApplicationContext接口的实现:

    FileSystemXmlApplicationContext:从xml文件中加载已经被定义的bean,需要提供的参数为完整的XML文件路径

    ClassPathXmlApplicationCOntext:从xml文件中加载已经被定义的bean,但从CLASSPATH加载xml文件

    package com.tutorialspoint;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    public class MainApp {
       public static void main(String[] args) {
          //第一步
          ApplicationContext context = new FileSystemXmlApplicationContext("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml");
          //第二步
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
          obj.getMessage();
       }
    }

    Spring Bean 的作用域

    singleton:是bean的默认作用域;当作用域为singleton时,IOC容器只会存在一个共享的bean实例,多次getBean时,返回的都是同一个Bean

    <bean id="..." class="..." scope="singleton">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    prototype:表示一个bean的定义对应多个对象实例,每次getbean时都会返回一个新的bean实例;

    spring的依赖注入

    基于构造函数的注入

    <!-- id是bean的id,用于识别bean; class是bean所对应的类-->
    <bean id="textEditor" class="com.tutorialspoint.TextEditor">    
          <!--constructor-arg表示基于构造函数注入 ,ref表示注入的值是引用而非一般的数值-->
          <constructor-arg ref="spellChecker"/>   
    </bean>
       <bean id="foo" class="x.y.Foo">
          <!-- 当构造函数存在多个参数时,按顺序定义即可按顺序传参-->
          <constructor-arg ref="bar"/>
          <constructor-arg ref="baz"/>
       </bean>

    基于设值函数的依赖注入

       <bean id="textEditor" class="com.tutorialspoint.TextEditor">
          <property name="spellChecker" ref="spellChecker"/>    <!-- property表示基于设值函数注入,设值函数的名字一定要是 setSpellChecker()-->
          <property name="name" value="John Doe"/>           <!-- name是属性的名字,value是属性的值-->
      </bean>

    基于注解的配置

    注解

    @required:用在set方法上,一旦用了这个注解,bean在初始化时就必须对这个值进行依赖注入;否则报错

    public class Zoo {
        private Dog dog ;
        public Dog getDog() {
            return dog;
        }
        @required     //如果xml文件中没有对Dog属性进行注入,则会报错
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    }  

    @Autowired:可以不写依赖注入的配置,让容器自己寻找依赖并注入

    public class Zoo {
        @Autowired        private Dog dog ;
        public Dog getDog() {
            return dog;
        }
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    }   

     基于注解的注入

    在xml配置中添加下列语句,告诉spring要用注解的方式进行配置

    <context:annotation-config/>
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class Product {     
    private int id; //在属性前加上Autowired注解,实现注入; //这时Category属性就可以不要set函数了,在xml中的Product的bean也不能再配置Category属性了;但product的bean还是需要的; //如果在xml中的product的bean中也配置了Category属性,则会按照xml优先的原则寻找属性对应的set函数或者构造函数,如果找不到则报错 @Autowired private Category category; public int getId() { return id; } public void setId(int id) { this.id = id; } //也可以在设值函数前加上Autowired注解,实现注入; //这种情况下同上,可以不用在xml文件中配置category属性,但product的bean还是需要声明的 @Autowired   public void setCategory(Category category) {     this.category = category;   } }

    此时的xml:仅仅去掉了对属性是引用的Category属性的配置,其它的并没有省略;(省略的是下方注释的那一行)

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context     
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
      
        <context:annotation-config/>
        <bean name="c" class="com.how2java.pojo.Category">
            <property name="name" value="category 1" />
        </bean>
        <bean name="p" class="com.how2java.pojo.Product">
            <property name="name" value="product1" />
    <!--         <property name="category" ref="c" /> -->
        </bean>
      
    </beans>

    进一步省略基于注解的注入

    先将xml中的什么都去掉,只新增一行<context:component-scan base-package="com.how2java.pojo"/>,这时告诉spring,bean在哪个java包下

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context     
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
      
        <context:component-scan base-package="com.how2java.pojo"/>
         
    </beans>

    然后在java文件中做如下改动

    package com.how2java.pojo;
    import javax.annotation.Resource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
     
    //@component表明Product类是bean,这相当于在xml中声明一个bean
    @Component("p")
    public class Product {
        //属性的初始化现在放在属性声明中进行
        private int id = 10;
        private String name="product 1";
        //同上,对Category属性进行自动注入
        @Autowired
        private Category category;
     
    }

    Spring AOP

    aop概念

    连接点(joinpoint):一个类或者一段程序拥有的具有边界性质的特定点,叫做连接点。

    切点(pointcut):是某些特定的连接点;如果用数据库的概念来比喻连接点和切点的关系,连接点相当于客观存在的记录数据,而切点相当于查询条件;

    增强(advice):增强是织入到连接点上的一段程序代码(就是一个方法);

    目标对象:要被织入代码的类

    切面:切面 = 增强 + 切点

    基于xml的aop

    服务类:

    import org.aspectj.lang.ProceedingJoinPoint;
    //增强所在的类 
    public class LoggerAspect {
        //增强,即要织入的方法
        public void log(JoinPoint joinPoint) throws Throwable {
            System.out.println("start log");
            return object;
        }
    }  

    xml配置:

    <!-- 声明业务类对象-->
    <bean name="s" class="com.how2java.service.ProductService">
    </bean> 
    <!-- 声明服务类对象-->
    <bean id="loggerAspect" class="com.how2java.aspect.LoggerAspect"/>
    
    <aop:config>
            <!-- id是切入点的名字,定义了一个切点 -->
            <!-- expression 表示满足这个expression 的方法在被调用之后,就会执行切面操作,相当于触发了切面;-->
            <!--第一个*表示返回值返回任意类型,第二个*表示任意方法,(..)表示方法的参数是任意数量和类型 --> 
            <aop:pointcut id="loggerCutpoint"  expression="execution(* com.how2java.service.ProductService.*(..)) "/>
            <!-- 定义了一个切面,切面 = 增强 + 切点--> 
            <!-- id是切面的名字, ref是增强所在的类-->  
            <aop:aspect id="logAspect" ref="loggerAspect">
                <!-- pointcut-ref 表示本切面和哪个切点相关联; method代表增强-->
                <!-- aop:after 表示要在何时调用增强;before在方法调用前,after在方法调用后,after-returning在方法执行成功后-->
                <!-- after-throwing在方法抛出异常后调用;around在方法调用前和调用后执行-->
                <aop:after pointcut-ref="loggerCutpoint" method="log"/>
            </aop:aspect>
    </aop:config>

    基于注解方式的aop

     业务类如下:

    package com.how2java.service;
    import org.springframework.stereotype.Component;
    //用component来声明这是一个bean
    @Component("s")
    public class ProductService {
        public void doSomeService(){
            System.out.println("doSomeService");
        }     
    }

    服务类如下:

    package com.how2java.aspect;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    //Aspect注解表示这是一个切面,component注解声明了一个bean
    @Aspect
    @Component
    public class LoggerAspect {
        //around注解表示对目标类中的某些方法进行切面操作 
        @Around(value="execution(*com.how2java.service.ProductService.*(..))")
        public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("start log:" + joinPoint.getSignature().getName());
            Object object = joinPoint.proceed();
            System.out.println("end log:" + joinPoint.getSignature().getName());
            return object;
        }
    }

    xml配置如下:

    <?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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context     
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">
        <!-- 下面两行是告诉spring应该扫描哪些包-->
        <context:component-scan base-package="com.how2java.aspect"/>
        <context:component-scan base-package="com.how2java.service"/>
      
        <aop:aspectj-autoproxy/> 
       
    </beans>

     

  • 相关阅读:
    [转]Kqueue与epoll机制
    [转]Docker中的镜像
    [转]linux awk命令详解
    [转]Linux Shell 1>/dev/null 2>&1 含义
    file_get_contents(): SSL operation failed with code 1...解决办法和stream_context_create作用
    PHP abstract与interface之间的区别
    PHP基于Redis的全局订单号id
    Eclipse for php+Xdebug,搭建php单步调试环境
    Eclipse launch configuration----Eclipse运行外部工具
    MySql 缓冲池(buffer pool) 和 写缓存(change buffer) 转
  • 原文地址:https://www.cnblogs.com/zhuqiwei-blog/p/10751778.html
Copyright © 2011-2022 走看看