码迷,mamicode.com
首页 > 编程语言 > 详细

框架之 spring

时间:2015-07-24 15:44:01      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

 

spring有两大特性,其一为ioc,其二为aop

1.ioc的理解

ioc为依赖注入,他的好处就是把创建对象的权利交给spring去管理,这样的好处是 将应用程序中的对象解耦,传统的方式程序中的对象与对象引用的对象相互依赖,这样就使得依赖性增高,增加耦合性。

解耦举例

不使用spring:action层中引用service,servicebean需要new一个实例。这样action和servicebean层耦合的。

使用spring:action层中引用service,servicebean只需声明即可,实例化是在spring容器内进行的,这样action和service层是解耦的

 

di为控制反转,以前创建对象的权利由应用程序,现在交给spring来管理 从应用层到ioc这就为控制反转。

ioc提供了两种容器:

1)bean工厂(BeanFactory),采用工厂模式,负责创建和分发bean对象,bean工厂还参与到bean的生命周期中,调用用户定义的初始化方法和销毁方法。

  bean工厂延迟加载所有bean,知道getBean方法被调用时才创建bean

2)应用上下文(ApplicationContext)建立在bean工厂之上,提供了系统架构服务。

  ApplicationContext提供了更多功能:
  文本信息解析工具,包括对国际化的支持
  载入文件资源的通用方法,如载入图片
  向注册为监听器的Bean发送事件
  是BeanFactory的完全超集
  ApplicationContext的三种常用实现:
  ClassPathXmlApplicationContext
  FileSystemXmlApplicationContext
  XmlWebApplicationContext
  如:ApplicationContext context=new ClassPathXmlApplicationContext(“xxx.xml”);
  可以通过ApplicationContext获得BeanFactory:

  BeanFactory factory=(BeanFactory)context;

 

下边重点说一些bean的生命周期

  容器寻找Bean的定义信息并将其实例化
  使用依赖注入
  如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法
  如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法
  如果有BeanPostProcessor和Bean关联,那么它们的postProcessBeforeInitialzation()方法被调用
  如果Bean实现了InitializbaleBean接口,那么调用他的afterPropertiesSet方法
  如果Bean指定了init-method方法,他将被调用
  如果有BeanPostProcessor和Bean关联,那么它们的postProcessorAfterInitialization()方法被调用
  Bean已经实例化出来了,可以被应用使用了
  如果Bean实现了DisposableBean接口,destroy()方法被调用
  如果指定了定制的销毁方法,就调用这个方法
首先BeanPostProcessor接口的作用是在处理bean的时候增加一些业务逻辑,InitializebaleBean接口和bean标签中的init-method是用于初始化bean,
<bean id="" class="" init-method="init"/>

 技术分享

关于bean的一些内容

  单例:通过getBean方法返回的对象总是一个对象
  多例:返回不同的对象
  <bean>的scope属性设置为singleton为单例,prototype为原型(多例)
   scope =singleton(单例,默认值) lazy-init才有效
  lazy-init=true 第一次getBean方法执行时创建bean
  vazy-init=false(默认值) 创建beanFactory时创建bean
  scope=prototype(多例) lazy-init无效 ,每次调getBean时都会创建bean
在ioc容器中实例化bean的三种方式
 1)用构造器实例化bean
  <bean id="target" class="target"></bean>
 2)通过静态工厂(在bean种定义一个静态方法,配置factory-method指定静态方法,运行时容器就会自动调用静态方法生成实例)
  <bean id="target" class="factory" factory-method=""></bean>
 3)通过实例工厂(要写两个bean,一个是要实例化的bean,另一个是工厂bean。容器先实例化工厂bean,然后调用工厂bean配置项factory-method中指定的方法,在方法中实例化bean)
  <bean id="target" factory-class="factoryId" factory-method=""></bean>
  <bean id="factoryId" class="target"></bean>
 
在bean中注入对象的方式
  1)利用set/get方法注入 
  <bean id="" class="">
    <property name="" ref=""></property>
  </bean>
 2).通过构造器注入
  <bean id="" class="">
    <constructor-arg index="" ref=""></constructor-arg>
  </bean>
 3).通过注解注入
 
谈一下ioc中用到的一些设计模式和方式
beanFactory采用的工厂模式,
如果配置bean  scope =singleton,则bean采用的是单例模式
在获取bean对象时采用的反射方式,通过反射类的class路径进行实例化,在该实例化过程中通过判断lazy-init来判断是生成目标对象还是代理对象,其中代理对象采用的是jdk代理。(hibernate中的懒加载采用的是cglib代理)
简单说一下两者的区别:
jdk代理为jdk自带的代理方式,通过实现InvocationHandler接口重写invoke方法,该代理类和目标类实现了同一接口。代理类生成方式是通过反射生成的。
cglib代理通过显示MethodInteceptor接口重写inteceptor方法,该代理类为目标类的子类。
随着jdk版本的不断升级,jdk代理的源码一部分被修改,jdk1.8中的效率已经远远大于cglib
具体代码请看文档
 
 
2.spring中的aop
aop就是面向切面编程的意思,采用的是动态代理模式,进行对方法的拦截,可以动态的添加方法,实现了功能上的解耦,一般用于管理事务和日志记录。
其中切面指的是一些你需要执行的公共方法,比如事务,日志
连接点为目标类的集合,比如service中的方法
切点为目标类
 
举例:
 

 

package com.mediaforce.crawl.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceLog {
    String description() default "";
}

 

  1 package com.mediaforce.crawl.aop;
  2 
  3 import java.lang.reflect.Method;
  4 import java.util.ArrayList;
  5 import java.util.Arrays;
  6 import java.util.Date;
  7 import java.util.List;
  8 
  9 import javax.annotation.Resource;
 10 import javax.servlet.http.HttpServletRequest;
 11 import javax.servlet.http.HttpSession;
 12 
 13 import org.aspectj.lang.JoinPoint;
 14 import org.aspectj.lang.annotation.After;
 15 import org.aspectj.lang.annotation.Aspect;
 16 import org.aspectj.lang.annotation.Before;
 17 import org.aspectj.lang.annotation.Pointcut;
 18 import org.slf4j.Logger;
 19 import org.slf4j.LoggerFactory;
 20 import org.springframework.stereotype.Component;
 21 import org.springframework.web.context.request.RequestContextHolder;
 22 import org.springframework.web.context.request.ServletRequestAttributes;
 23 
 24 import com.mediaforce.crawl.model.Listpage;
 25 import com.mediaforce.crawl.model.TaskLog;
 26 import com.mediaforce.crawl.model.Websource;
 27 import com.mediaforce.crawl.service.CrawlService;
 28 import com.mediaforce.crawl.service.TaskLogService;
 29 
 30 @Aspect
 31 @Component
 32 public class SystemLogAspect {
 33     @Resource
 34     private TaskLogService taskLogService;
 35     
 36     @Resource
 37     private CrawlService crawlService;
 38 
 39     private static final Logger logger = LoggerFactory
 40             .getLogger(SystemLogAspect.class);
 41 
 42     // 层切入点
 43     @Pointcut("@annotation(com.mediaforce.crawl.aop.SystemServiceLog)")
 44     public void serviceAspect() {
 45     }
 46 
 47     
 48     @Before("serviceAspect()")
 49     public void doBefore(JoinPoint joinPoint){
 50        logger.error("=====日志前置通知开始=====");
 51         
 52         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
 53                 .getRequestAttributes()).getRequest();
 54         HttpSession session = request.getSession();
 55         // 读取session中的用户
 56         String username = (String) session.getAttribute("username");
 57 
 58         try{
 59             String action="";
 60             String msg="";
 61             String description =getServiceMthodDescription(joinPoint);
 62             
 63             Object[] args = joinPoint.getArgs();
 64             
 65             if("删除网站资源".equals(description)){
 66                 action="删除网站资源";
 67                 msg=this.getMsg(args, description);
 68             }else if("删除列表页".equals(description)){
 69                 action="删除列表页";
 70                 msg=this.getMsg(args, description);
 71             }else if("增加或者修改列表页".equals(description)){
 72                 Listpage lptemp=(Listpage) args[0];
 73                 if(lptemp.getId()==null){
 74                     action="增加列表页";
 75                     msg=lptemp.getUrl();
 76                 }
 77                 action ="修改列表页";
 78                 msg=this.getMsg(args, description); 
 79             }else if("增加或者修改网站资源".equals(description)){
 80                 Websource wstemp=(Websource) args[0];
 81                 if(wstemp.getId()==null){
 82                     action="增加网站资源";
 83                     msg=wstemp.getUrl();
 84                 }
 85                 action ="修改网站资源";
 86                 msg=this.getMsg(args, description);
 87             }
 88             
 89 
 90             
 91             TaskLog taskLog = new TaskLog();
 92             taskLog.setMsg(msg);
 93             taskLog.setAction(action);
 94             taskLog.setCreatetime(new Date());
 95             taskLog.setStatus(username);
 96             taskLog.setTaskid(1l);
 97             
 98             session.setAttribute("tasklog", taskLog);
 99           //  taskLogService.saveOrUpdateTaskLog(taskLog);
100           
101         }catch(Exception e){
102             e.printStackTrace();
103             logger.error("=====日志前置通知异常=====");
104         }
105     }
106     @After("serviceAspect()")
107     public void doAfter(JoinPoint joinPoint){
108         logger.error("=====日志后置通知开始=====");
109         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
110                 .getRequestAttributes()).getRequest();
111         HttpSession session = request.getSession();
112         TaskLog taskLog  = (TaskLog) session.getAttribute("tasklog");
113         taskLogService.saveOrUpdateTaskLog(taskLog);
114         logger.error("=====日志后置通知结束=====");
115     }
116     
117     
118     /**
119      * 获取msg详细信息
120      * @param tempIds
121      * @param s
122      * @return
123      */
124     public String getMsg(Object[] o,String s){
125         List<Long> ids = new ArrayList<Long>();
126         
127         if(s.contains("网站资源")){
128             if(s.contains("删除")){
129                 Long[] temp=(Long[]) o[0];
130                 ids=Arrays.asList(temp);
131             }else{
132                 Websource ws=(Websource) o[0];
133                 ids.add(ws.getId());
134             }
135             
136             List<Websource> list=crawlService.getWebsources(ids);
137             StringBuffer names=new StringBuffer();
138             for(Websource w:list){
139                 names=names.append(w.getName()).append(":").append(w.getUrl()).append(";");
140             }
141             return names.toString();
142             
143         }else {
144             if(s.contains("删除")){
145                 Long[] temp=(Long[]) o[0];
146                 ids=Arrays.asList(temp);
147             }else{
148                 Listpage lp=(Listpage) o[0];
149                 ids.add(lp.getId());
150             }
151             
152             List<Listpage> list = crawlService.getListPages(ids);
153             StringBuffer names=new StringBuffer();
154             for(Listpage w:list){
155                     names.append(w.getUrl()).append(";");
156                     System.out.println(names);
157             }
158             return names.toString();
159         }
160         
161         
162     }
163     
164     /**
165      * 获取注解中对方法的描述信息
166      * 
167      * @param joinPoint
168      * @return
169      * @throws Exception
170      */
171 
172     public static String getServiceMthodDescription(JoinPoint joinPoint)
173             throws Exception {
174         String targetName = joinPoint.getTarget().getClass().getName();
175         String methodName = joinPoint.getSignature().getName();
176         Object[] arguments = joinPoint.getArgs();
177         Class targetClass = Class.forName(targetName);
178         Method[] methods = targetClass.getMethods();
179         String description = "";
180         for (Method method : methods) {
181             if (method.getName().equals(methodName)) {
182                 Class[] clazzs = method.getParameterTypes();
183                 if (clazzs.length == arguments.length) {
184                     description = method.getAnnotation(SystemServiceLog.class)
185                             .description();
186                     break;
187                 }
188             }
189         }
190         return description;
191     }
192 
193 }

 

 

框架之 spring

标签:

原文地址:http://www.cnblogs.com/amei0/p/4673344.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!