首先要知道 Spring两大核心IOC和AOP(Java轻量级业务层框架Spring两大核心IOC和AOP原理

IOC:

1.从Java最基本的创建对象开始

  如Interface Driven Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:AInterface a =   new AInterfaceImp(); 这样一来,耦合关系就产生了,如:

classA
{
AInterface a; A(){} AMethod()//一个方法
{
a = new AInterfaceImp();
}
}
  Class A与AInterfaceImp就是依赖关系,如果想使用AInterface的另外一个实现就需要更改代码了。当然我们可以建立一个Factory来根据条件生成想要的AInterface的具体实现,即:
InterfaceImplFactory
{
AInterface create(Object condition)
{
if(condition == condA)
{
return new AInterfaceImpA();
}
else if(condition == condB)
{
return new AInterfaceImpB();
}
else
{
return new AInterfaceImp();
}
}
}
 
  表面上是在一定程度上缓解了以上问题,但实质上这种代码耦合并没有改变。
 
2.再开始说Spring的原理——IOC
  通过IoC模式可以彻底解决这种耦合,它把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中,这可能就是“依赖注入”说法的来源了。
  IoC模式,系统中通过引入实现了IoC模式的IoC容器,即可由IoC容器来管理对象的生命周期、依赖关系等,从而使得应用程序的配置和依赖性规范与实际的应用程序代码分开。其中一个特点就是通过文本的配置文件进行应用程序组件间相互关系的配置,而不用重新修改并编译具体的代码。
  可以把IoC模式看做是工厂模式的升华(动态代理),可以把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java 的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
(JVM允许Java程序在运行时,去查找Java对象Class.forName(包名+类名),也是动态代理实现的方式,简单工厂定义一个外部键值文件,在工厂里面加载该文件,当要创建某个对象的时候,通过读取文件用键获取值,然后用Class.forName(包名+类名)可以实现一个比较简单的动态代理创建一个对象)
  IoC中最基本的Java技术就是“反射”编程。反射又是一个生涩的名词,通俗的说反射就是根据给出的类名(字符串)来生成对象。这种编程方式可以让对象在生成时才决定要生成哪一种对象。反射的应用是很广泛的,像Hibernate、Spring中都是用“反射”做为最基本的技术手段。
  IoC最大的好处是什么?因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是实现于某种接口的),只要修改XML就可以了,这样我们甚至可以实现对象的热插拔(有点像USB接口和SCSI硬盘了)。
  IoC最大的缺点是什么?(1)生成一个对象的步骤变复杂了(事实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。(2)对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。(3)缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺陷所在。
 
AOP
 
1.先说为什么要用AOP
  比如说登录拦截,按照OOP思想,创建一个抽象类,然后让各个要检验是否登录的类继承该抽象类进行登录拦截,但是由于Java单继承的特点,有些类是无法再次继承的,这样就处理起来就很麻烦,不可能在每个类中写拦截的方法并在需要判断的地方做判断拦截处理,这样代码盈余,重用性低,维护性极差。因此这时候OOP就不适用了。(用接口的做法也是不行的,每个实现类都要实现该方法,当然如果用公共类去做这块的处理,耦合太高,不便于维护。)  
但是要记住AOP实际上是一种编程思想,AOP面向切面编程基于IoC,是对OOP的有益补充。
 
2.再开始说Spring的原理——AOP

  Filter的实现、interceputor的实现以及struts2的拦截器的实现都是AOP思想的体现

  将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即切面。所谓“切面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,比如日志记录,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
 
下面一个例子来说明问题
引用于:http://supben.iteye.com/blog/1520126
  先看 advice 类

package com.supben.advice;

import java.lang.reflect.Method;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice; /**
* 实现spring advice 接口
*
* @author shencl
*
*/
public class TestAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice { private static final Logger log = LoggerFactory.getLogger(TestAdvice.class); /**
* before 通知
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
log.info(target.getClass().getSimpleName() + "类的" + method.getName() + "方法,执行TestAdvice的before通知");
     // 通知要做的业务
if (method.getName().startsWith("get")) {
log.info("只有方法名是以get开始的方法,才会执行到这句话....");
}
} /**
* after 通知
*/
public void afterReturning(Object arg0, Method method, Object[] arg2, Object target) throws Throwable {
log.info(target.getClass().getSimpleName() + "类的" + method.getName() + "方法,执行TestAdvice的after通知");
} /**
* 异常通知
*/
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
log.info(target.getClass().getSimpleName() + "类的" + method.getName() + "方法,执行TestAdvice的throwing通知");
} }

配置文件

<?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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <context:annotation-config />
<!-- 扫描com.supben 下所有的包-->
<context:component-scan base-package="com.supben" /> <bean id="testAdvice" class="com.supben.advice.TestAdvice" />
<aop:config>
<aop:advisor pointcut="execution(* *..service.*Service.*(..))"
advice-ref="testAdvice" />
</aop:config> </beans>

service接口

    package com.supben.service;  

    public interface FirstService {  

        public void get();  

        public void exception();
}

service实现类

package com.supben.service.impl;  

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import com.supben.service.FirstService; @Service("firstService")
public class FirstServiceImpl implements FirstService {
private static final Logger log = LoggerFactory.getLogger(FirstServiceImpl.class); public void get() {
log.info("方法执行ing.....");
} public void exception() {
throw new RuntimeException("测试异常");
}
}

测试类

    package com.supben.test;  

    import junit.framework.TestCase;  

    import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.supben.service.FirstService;
import com.supben.spring.SpringContextUtil; public class ServiceTest extends TestCase {
/**
* 装载spring 配置文件
*/
static {
new ClassPathXmlApplicationContext("application.xml");
} @Test
public void testGet() {
FirstService service = SpringContextUtil.getBean("firstService");
service.get();
} @Test
public void testGet2() {
FirstService service = SpringContextUtil.getBean("firstService");
service.exception();
}
}

测试结果:

2012-05-09 15:10:10,028 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的get方法,执行TestAdvice的before通知

2012-05-09 15:10:10,030 INFO [com.supben.advice.TestAdvice] - 只有方法名是以get开始的方法,才会执行到这句话....

2012-05-09 15:10:10,032 INFO [com.supben.service.impl.FirstServiceImpl] - 方法执行ing.....

2012-05-09 15:10:10,032 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的get方法,执行TestAdvice的after通知

2012-05-09 15:10:10,035 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的exception方法,执行TestAdvice的before通知

2012-05-09 15:10:10,035 INFO [com.supben.advice.TestAdvice] - FirstServiceImpl类的exception方法,执行TestAdvice的throwing通知

结果分析:

get方法满足执行之前会 执行 before通知,执行完成后会执行after通知。

exception方法执行之前会执行before 通知,因为方法名不是以get开头,所以不会执行before通知的业务逻辑。然后出现异常了会执行throwing通知,因为出异常了,方法没有执行完毕,所以不会触发after通知。

概念:

切面(aspect):
翻译成外貌更合适:整个程序相当于一个密封的圆柱体,即一个外貌,现在要面向这个东西编程,在不改变原来类(FirstServiceImpl)的情况下,改变里边的代码。通知(advice):TestAdvice里边的before,after,throwing方法都是通知。
常见的有前置通知,后置通知,异常通知。

切点(cut-point):定义通知应该应用在哪些地方,本例是FirstServiceImpl中的get方法和exception方法,一般用正则表达式定义。

切点表达式:配置文件中的execution(* *..service.*Service.*(..))
是一个切点表达式,表示的是一个一个的方法.比如本例中的表达式,意思是 包目录的最后一级是service,类/接口名 后缀为Service的
class文件里的,方法名为任意名称,参数个数不限的 方法。 * 表示任意,(..)表示方法参数个数不限。

目标对象(traget):FirstService就是目标对象。

此外还有两个重要的概念

引入(Introduction):允许为已存在类添加新方法和属性。

代理(Proxy):将通知应用到目标对象后创建的对象。

 

关于面试别问及Spring如何回答思路总结!的更多相关文章

  1. BAT面试官告诉你如何回答你的职业规划

    前言(Why) 在面试中不论是在一面二面三面这种技术面,还是在最后的hr面,经常会被人问及,"谈谈你的职业规划"这种问题,我们回答的很可能会给我们的面试表现加分,如果回答地不好,对 ...

  2. 面试常问Spring IOC,不得不会。

    广义的 IOC IoC(Inversion of Control) 控制反转,即“不用打电话过来,我们会打给你”. 两种实现: 依赖查找(DL)和依赖注入(DI). IOC 和 DI .DL 的关系( ...

  3. java web方面的面试问题,Spring MVC方面的面试问题,摘自java web轻量级开发面试教程

    本文摘自java web轻量级开发面试教程: https://baike.baidu.com/item/Java%20Web%E8%BD%BB%E9%87%8F%E7%BA%A7%E5%BC%80%E ...

  4. 面试官:“谈谈Spring中都用到了那些设计模式?”。

    我自己总结的Java学习的系统知识点以及面试问题,已经开源,目前已经 41k+ Star.会一直完善下去,欢迎建议和指导,同时也欢迎Star: https://github.com/Snailclim ...

  5. 《PHP程序员面试笔试宝典》——如何回答算法设计问题?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 程序员面试中的很多算法设计问题,都是历年来各家企业的"炒现饭",不管求职者以前对算法知识掌握得是否扎 ...

  6. 《PHP程序员面试笔试宝典》——如何回答快速估算类问题?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 有些大企业的面试官,总喜欢出一些快速估算类问题,对他们而言,这些问题只是手段,不是目的,能够得到一个满意的结果固然是他们 ...

  7. 《PHP程序员面试笔试宝典》——如何回答非技术性问题?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 评价一个人的能力,除了专业能力,还有一些非专业能力,如智力.沟通能力和反应能力等,所以在IT企业招聘过程的笔试.面试环节 ...

  8. 《PHP程序员面试笔试宝典》——如何回答技术性的问题?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 程序员面试中,面试官会经常询问一些技术性的问题,有的问题可能比较简单,都是历年的面试.笔试真题,求职者在平时的复习中会经 ...

  9. 基于spring的placeholder思路处理配置信息敏感信息加密解密的实践

    基于Spring的placeholder处理思路,实现系统配置信息敏感信息的加密解密处理. 我们的处理方案,是基于类org.springframework.beans.factory.config.P ...

随机推荐

  1. Exec in Job and NewQuery

    1.背景 Job:一个步骤执行两个存储过程ProcA.ProcB.ProcA定义一个游标,从表TabA中检索数据,逐条插入到表TabB.如果某条数据不满足TabB上的约束(比如非空)导致插入失败.那么 ...

  2. Fatal error: Call to undefined function curl_init()问题

    最近分别在win7和Win8.win10 上分别安装php 高版本!都遇到了这个问题! 一.win7系统, apache2.2/apache2.4, php5.2升级到5.4. 这个比较容易: 1. ...

  3. 总结ThinkPHP使用技巧经验分享(一)

    约定:1.所有类库文件必须使用.class.php作为文件后缀,并且类名和文件名保持一致2.控制器的类名以Action为后 缀3.模型的类名以Model为后缀,类名第一个字母须大写4.数据库表名全部采 ...

  4. ZOJ 2412 Farm Irrigation

    Farm Irrigation Time Limit: 2 Seconds      Memory Limit: 65536 KB Benny has a spacious farm land to ...

  5. 自定义cell侧滑删除

    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return Y ...

  6. io与nio的区别

    传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大.使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数 ...

  7. HTML5的postMessage使用记要////////////////////////////zzzzzzzz

    2014-11-09 20:17:27http://jo2.org/html5-js-postmessage-tips/--点击数:2710     HTML5提出了一个新的用来跨域传值的方法,即po ...

  8. zzuli-小火山的跳子游戏

    Description   小火山和火山火山在一块玩跳子游戏.规则如下:   1:跳子的起始位置为0,棋盘大小从1到N   2:每次跳子跳k步. 例如当前位置为i, 那么下一步为i + k   3:跳 ...

  9. Java被忽略的基本知识(四)

    Java IO(不是一般的重要) 54.IO中的流:字节流(InputStream.OutputStream).字符流(Reader.Writer).转换流(InputStreamReader.Out ...

  10. 夺命雷公狗-----React---23--小案例之react经典案例todos(完成添加任务)

    我们这次来处理用户添加的数据,我们还是赵老规矩看看组建大致图... 子组件对父组建进行数据的传递其实是react内部的机智进行处理的了,, 代码如下所示: <!DOCTYPE html> ...