spring的IOC和AOP

 

1.Spring容器实例化

 例子1:
  String conf = "applicationContext.xml";
  ApplicationContext ac = new ClassPathXmlApplicationContext(conf);
  CostAction action = (CostAction)ac.getBean("costAction");
  System.out.println(action.getClass().getName());
  action.addCost();
  
 例子2:
  String[] confs = {"applicationContext.xml"};
  ApplicationContext ac = new ClassPathXmlApplicationContext(confs);
  BeanUtil util = (BeanUtil)ac.getBean("beanUtil");
  util.showMessage();
  
2.容器对Bean组件管理

 <!-- 定义一个Bean组件,id|name用于指定组件标示符,class用于指定组件实现类 -->

 <bean   id="costDao"
   scope="singleton"
   lazy-init="true"
   init-method="myinit"
   class="org.tarena.dao.impl.JdbcCostDAO" >
 </bean>

 注:
  id|name:用于指定组件标示符
  class:用于指定组件实现类
  scope:singleton单例,prototype非单例
  lazy-init:单例延迟创建
  init-method:设置初始化参数的方法
  destroy-method:销毁之前调用的方法

3.IOC机制

 原理DI技术实现:依赖注入。为Bean对象里的属性注入值
 
 3.1.DI注入技术有以下几种实现
 
  1).setter方式注入,name与setter方法一致
  
   <property name="Bean对象里的属性" ref="Bean对象的ID"></property>
  
  2).构造方法注入 index参数索引
  
   <constructor-arg index="0" ref="Bean对象的ID"></constructor-arg>

 3.2.注入各种不同的类型的数据

  1)注入一个Bean对象
  
   <property name="被注入的属性名字" ref="Bean的ID名称"> </property>
  
  2)注入一个基本类型对象
  
   <property name="被注入的属性名字" value="基本类型值"> </property>
  
  3)注入list
  
   例子1:
    <property name="被注入的属性名字">
     <list>
      <value>值1</value>
      <value>值2</value>
      <value>值3</value>
     </list>
    </property>
    
   例子2:
    
    <property name="被注入的属性名字">
     <list>
      <ref>值</ref>
      <ref>值</ref>
      <ref>值</ref>
     </list>
    </property>

  4)注入set集合

    <property name="被注入的属性名字">
     <set>
      <value>值</value>
      <value>值</value>
      <value>值</value>
     </set>
    </property>

  5)注入map集合

    <property name="被注入的属性名字">
     <map>
      <entry key="" value=""></entry>
      <entry key="" value=""></entry>
      <entry key="" value=""></entry>
     </map>
    </property>

  6)注入Properties

    <property name="被注入的属性名字">
     <props>
      <prop key="">值</prop>
      <prop key="">值</prop>
     </props>
    </property>

4.AOP机制

 AOP机制的实现原理:动态代理机制

 4.1.AOP使用步骤
 
  a.引入Spring的IOC和AOP开发包
  
  b.添加Spring容器配置文件
  
  c.将共通处理封装成一个独立Bean组件
  
  d.采用AOP配置将Bean组件作用到其它目标组件及其方法上

  AOP配置 例子:
   
   <!-- 利用AOP机制 -->
   <bean id="loggerBean"
    class="org.tarena.aspect.LoggerBean">
   </bean>
   
   <aop:config>
    <!-- 切入点,指定目标组件 -->
    <aop:pointcut id="actionPointcut"
     expression="within(org.tarena.action..*)"/>
    <!-- 方面,将loggerBean定义为方面组件 -->
    <aop:aspect id="loggerAspect" ref="loggerBean">
     <!-- 通知,指定loggerBean功能在action方法前调用 -->
     <aop:around pointcut-ref="actionPointcut"
      method="logger"/>
    </aop:aspect>
   </aop:config>

 4.2.AOP相关概念
 
  方面(Aspect):封装共通处理的组件
  
  切入点(Pointcut):目标对象及方法
  
  连接点(JoinPoint):方面和某一个目标方法的关联点
  
  通知(Advice):指定方面功能在目标对象方法上执行的时机
  
  目标组件(Target):使用方面功能的Bean组件
  
  
 4.3.切入点表达式
 
   利用表达式指定目标组件及方法
   
  a.方法限定表达式
  
     execution(修饰符? 返回类型 方法名(参数列表) throws异常?)
   
   示例1:匹配容器中所有组件以add开始的方法
       execution(* add*(..))
   示例2:匹配CostService组件的所有方法
       execution(* org.tarena.service.CostService.*(..))
   示例3:匹配service包下所有类的所有方法
       execution(* org.tarena.service.*.*(..))
   示例4:匹配service包下及其子包中所有类的所有方法
       execution(* org.tarena.service..*.*(..)
        
  b.类型限定表达式
  
     within(类型)
      
    示例1:匹配CostService类中所有方法
      within(org.tarena.service.CostService)
    示例2:匹配service包下所有类的所有方法
      within(org.tarena.service.*)
    示例3:匹配service包及其子包所有类所有方法
      within(org.tarena.service..*)
      
  注:以上表达式可以用&&,||连接在一起,也可用!,(&amp;):在xml中代表(&&)
  
      
 4.4.通知类型
  
   try{
    
     
        // 前置通知--执行方面组件 <aop:before>
        // 执行目标方法
        // 后置通知--执行方面组件 <aop:after-returnning>
    
     //以上加起来等于环绕通知
     //  ||
     //环绕通知=前置通知+后置通知 <aop:around>
     }catch(Exception ex){
        // 异常通知--执行方面组件 <aop:after-throwing>
     }finally{
        // 最终通知--执行方面组件 <aop:after>
     }
    
5.环绕通知:记录操作日志

 5.1.配置
 
  <!-- 利用AOP机制 -->
  <bean id="loggerBean"
   class="org.tarena.aspect.LoggerBean">
  </bean>
  
  <aop:config>
   <!-- 切入点,指定目标组件 -->
   <aop:pointcut id="actionPointcut"
    expression="within(org.tarena.action..*)"/>
   <!-- 方面,将loggerBean定义为方面组件 -->
   <aop:aspect id="loggerAspect" ref="loggerBean">
    <!-- 通知,指定loggerBean功能在action方法前调用 -->
    <aop:around pointcut-ref="actionPointcut"
     method="logger"/>
   </aop:aspect>
  </aop:config>
  
  
 5.2.组件中的代码
 
  环绕通知,自动给方面组件的方法传入参数:连接点 ProceedingJoinPoint pjp
  
  通过连接点可以获得:
   
   要执行的目标组件名称:String pjp.getTarget().getClass().getName();
   要执行的目标方法名称:String pjp.getSignature().getName();
 
  执行目标方法的方法:Object retVal = pjp.proceed();
      // 在这之前是前置处理,之后是后续操作,类似于struts的拦截起
 
  方面组件方法返回:return retVal
  
   例子:
    // 环绕通知处理方法,采用<aop:around>配置
    public Object logger(ProceedingJoinPoint pjp) throws Throwable{
     // 获取要执行的目标组件名称
     String clazzName =
      pjp.getTarget().getClass().getName();
     // 获取要执行的目标方法名称
     String methodName =
      pjp.getSignature().getName();
     // 利用类名.方法名去opt.properties中获取操作名
     String key = clazzName+"."+methodName;
     String name = PropertiesUtil.getValue(key);
     System.out.println("XXX执行了"+name+"操作"+new Date());
     Object retVal = pjp.proceed();// 执行目标方法
     // TODO 后续处理
     return retVal;
    }

6.异常通知:记录异常日志

 6.1.配置
 
  <!-- 利用AOP机制 -->
  <bean id="exceptionBean"
   class="org.tarena.aspect.ExceptionBean">
  </bean>
  <aop:config>
   <!-- 切入点,指定目标组件 -->
   <aop:pointcut id="actionPointcut"
    expression="within(org.tarena.action..*)"/>
   <!-- 定义记录异常的方面组件 -->
   <aop:aspect id="exceptionAspect" ref="exceptionBean">
    <!-- 采用异常通知作用到action上 -->
    <aop:after-throwing pointcut-ref="actionPointcut"
     method="logger" throwing="ex"/>
   </aop:aspect>
  </aop:config>

 6.2.方面组件中代码
 
  Logger logger = Logger.getLogger(ExceptionBean.class);
  // 记录目标方法抛出的异常信息
  public void logger(Exception ex){
   logger.error("发生异常"+ex);
   StackTraceElement[] els = ex.getStackTrace();
   logger.error(els[0]);
  }

7.解析Properties

 解决中文编码问题:
 java中的native2ascii
   
  public class PropertiesUtil {
   private static Properties pros = new Properties();
   static {
    InputStream in = PropertiesUtil.class
     .getClassLoader().getResourceAsStream(
       "opt.properties");
    try{
     pros.load(in);
    }catch(Exception ex){
     ex.printStackTrace();
    }
   }
   
   public static String getValue(String key){
    String val = pros.getProperty(key);
    if(val == null){
     return "";
    }
    return val;
   }
  }

8.log4j

  日志器组件(Logger)
  输出器组件(Appender)
  布局器组件(Layout)
  
  ConsoleAppender:控制台输出
  FileAppender:输出到文件

 8.1.log4j.properties配置文件
 
  #log4j.properties
  #log4j.rootLogger=level,appender1,appender2..
  log4j.rootLogger=error,myconsole
  #appender
  log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
  #log4j.appender.myconsole=org.apache.log4j.FileAppender
  #log4j.appender.myconsole.File=D:\\log.txt
  #layout
  log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout
  
 8.2.级别有低到高
 
  Logger logger = Logger.getLogger(TestLog4j.class);

  logger.debug("调试信息");
  logger.info("普通信息");
  logger.warn("警告信息");
  logger.error("异常信息");
  logger.fatal("致命信息");

9.解析xml
  
 public class PrivilegeReader {
 
  private static List<Privilege> modules = new ArrayList<Privilege>();
  static {
   InputStream xml = PrivilegeReader.class.getClassLoader()
     .getResourceAsStream("privileges.xml");
   modules = toModuleList(xml);
  }
 
  // 通过id获取name
  public static String getModuleNameById(String id){
   List<Privilege> modules = getModules();
   for(Privilege module : modules){
    if(module.getId().equals(id)){
     return module.getName();
    }
   }
   return "";
  }
  private static List<Privilege> toModuleList(InputStream xml) {
   List<Privilege> modules = new ArrayList<Privilege>();
 
   try {
 
    SAXReader reader = new SAXReader();
    Document doc = reader.read(xml);
    Element root = doc.getRootElement();
 
    List<Element> moduleElements = root.elements("privilege");
 
    for (Element moduleElement : moduleElements) {
     //Privilege是一个实体类有id,name,urls属性
     Privilege module = new Privilege();
 
     module.setId(moduleElement.attributeValue("id"));
     module.setName(moduleElement.elementText("name"));
 
     Element urlElement = moduleElement.element("urls");
     List<Element> urlElements = urlElement.elements();
     List<String> urls = new ArrayList<String>();
 
     for (Element element : urlElements) {
      urls.add(element.getText());
     }
     module.setUrls(urls);
 
     modules.add(module);
 
    }
 
    return modules;
 
   } catch (DocumentException e) {
    e.printStackTrace();
    throw new RuntimeException("", e);
   }
  }
 
  public static List<Privilege> getModules() {
   return modules;
  }
 
  public static void main(String[] args) {
   List<Privilege> list = PrivilegeReader.getModules();
   for (Privilege p : list) {
    System.out.println(p.getId() + " " + p.getName()+""+p.getUrls());
   }
  }
 
 }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值