AOP的理解:


面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP的功能将切面织入到主业务逻辑中。
所谓交叉业务逻辑是指,通用的、与主业务逻辑无关的代码,如安全检查、事务、日志等。


使用AOP编程思想的好处:


若不使用AOP,则会出现代码纠缠,即交叉业务逻辑与主业务逻辑混合在一起。这样,会使主业务逻辑变的混杂不清。
业务逻辑的增强


如何搭建AOP编程环境:


导入jar包,两个jar包(aop/aopalliance)


附码:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="Index of /schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        Index of /schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 定义目标 -->
       <bean id="someServiceimpl" class="cn.msk.service.impl.SomeServiceimpl"></bean> 
       <!-- 切面:前置通知 -->
       <bean id="mymethodBefor" class="cn.msk.aspect.MymethodBefor"></bean>
       <!-- 切面:后置通知 -->
       <bean id="houzhitouzhi" class="cn.msk.aspect.houzhitouzhi"></bean>
       <!-- 切面:环绕通知 -->
       <bean id="haunrao" class="cn.msk.aspect.haunrao"></bean>
       <!-- 切面:异常通知 -->
       <bean id="myyihcang" class="cn.msk.aspect.Myyihcang"></bean>
       
       <!-- 注册切面 -->
       <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
       	<!-- 指定目标对象 -->
       	<property name="target" ref="someServiceimpl"></property>
       	<!-- 指定目标类实现的所有接口 -->
       	<property name="interfaces" value="cn.msk.service.SomeService"></property>
       	<!-- 指定切面 -->
       	<property name="interceptorNames" value="myyihcang"></property>
       </bean>
       
</beans>


aop场景 java java aop ioc_aop场景 java


业务层:Service

里面有:

SomeService接口/SomeServiceImpl实现类


package cn.msk.service;

public interface SomeService {
	void doSome();
	String doOther();
}


实现类:


package cn.msk.service.impl;

import cn.msk.service.SomeService;

public class SomeServiceimpl implements SomeService{

	@Override
	public void doSome() {
		System.out.println("SomeServiceimpl.doSome()"+"方法执行"+1/0);
		
	}

	@Override
	public String doOther() {
		System.out.println("SomeServiceimpl.doOther()"+"方法执行");
		return "Love";
	}

}


定义一个切面包(aspect)存放切面方法:

环绕通知:附码


package cn.msk.aspect;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class haunrao implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation fanhuizhi) throws Throwable {
	System.out.println("环绕通知执行前");
	//调用目标方法
	Object proceed = fanhuizhi.proceed();
	if (proceed != null) {
		proceed=((String)proceed).toUpperCase();
	}
	System.out.println("环绕通知执行后");
		return proceed;
	}

}


后置通知:


package cn.msk.aspect;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class houzhitouzhi implements AfterReturningAdvice {
	/**
	 * 切面:后置通知
	 * 
	 * returnValue:目标方法的返回值
	 */
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("后置方法的返回值");
		if (returnValue !=null) {
			System.out.println("如果不为空则输出:"+((String)returnValue).toUpperCase());
		}
	}

}


前置通知:


package cn.msk.aspect;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MymethodBefor implements MethodBeforeAdvice {

	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("spring框架,把简单的东西复杂化,让别人看不懂!");
		
	}

}


异常通知:


package cn.msk.aspect;

import org.springframework.aop.ThrowsAdvice;

public class Myyihcang implements ThrowsAdvice {
	public void afterThrowing(Exception ex) {
		System.out.println("异常通知执行");
	}
}



Spring、AspectJ和AOP三者之间的关系:


对于AOP这种编程思想,很多框架都进行了实现。Spring就是其中之一,可以完成面向切面编程。
然而,AspectJ也实现了AOP的功能,且其实现方式更为简捷,使用更为方便,而且还支持注解式开发。
所以,Spring又将AspectJ的对于AOP的实现也引入到了自己的框架中。
在Spring中使用AOP开发时,一般使用AspectJ的实现方式。


spectJ支持的常见通知:


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



对spring的详细说明:

Spring是什么?为什么使用Spring?


Spring框架是一个为Java应用程序的开发提供了综合、广泛的基础性支持的Java平台。
Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发。
Spring框架本身亦是按照设计模式精心打造,这使得我们可以在开发环境中安心的集成Spring框架,不必担心Spring是如何在后台进行工作的。

Dependency Injection(DI) 方法使得构造器和JavaBean properties文件中的依赖关系一目了然。
与EJB容器相比较,IoC容器更加趋向于轻量级。
这样一来IoC容器在有限的内存和CPU资源的情况下进行应用程序的开发和发布就变得十分有利。
Spring并没有闭门造车,Spring利用了已有的技术比如ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其他视图技术。
Spring框架是按照模块的形式来组织的。
由包和类的编号就可以看出其所属的模块,开发者仅仅需要选用他们需要的模块即可。
要测试一项用Spring开发的应用程序十分简单,因为测试相关的环境代码都已经囊括在框架中了。
更加简单的是,利用JavaBean形式的POJO类,可以很方便的利用依赖注入来写入测试数据。
Spring的Web框架亦是一个精心设计的Web MVC框架,为开发者们在web框架的选择上提供了一个除了主流框架比如Struts、过度设计的、不流行web框架的以外的有力选项。
Spring提供了一个便捷的事务管理接口,适用于小型的本地事物处理(比如在单DB的环境下)和复杂的共同事物处理(比如利用JTA的复杂DB环境)。


Spring有哪些特性?


轻量——从大小与开销两方面而言Spring都是轻量的。
完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。
此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。

控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。
当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。
你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。
应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。
然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。
Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。
它们也为Spring中的各种模块提供了基础支持。


Spring的重要特征有哪些?


AOP和IoC


Spring的IOC(控制反转),主要的作用是什么,程序中如何体现Spring的控制反转?


Rod Johnson是第一个高度重视以配置文件来管理Java实例的协作关系的人,他给这种方式起了一个名字:控制反转(Inverse of Control,IoC)。
后来Martine Fowler为这种方式起了另一个名称:依赖注入(Dependency Injection),因此不管是依赖注入,还是控制反转,其含义完全相同。
当某个Java对象(调用者)需要调用另一个Java对象(被依赖对象)的方法时,在传统模式下通常有两种做法:
原始做法: 调用者主动创建被依赖对象,然后再调用被依赖对象的方法。
简单工厂模式: 调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再调用被依赖对象的方法。

注意上面的主动二字,这必然会导致调用者与被依赖对象实现类的硬编码耦合,非常不利于项目升级的维护。
使用Spring框架之后,调用者无需主动获取被依赖对象,调用者只要被动接受Spring容器为调用者的成员变量赋值即可,由此可见,使用Spring后,调用者获取被依赖对象的方式由原来的主动获取,变成了被动接受——所以Rod Johnson称之为控制反转。
另外从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量——相当于为调用者注入它依赖的实例,因此Martine Fowler称之为依赖注入。


bean的作用域有哪些?各有什么不同?


当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。
Spring支持如下5种作用域:
singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。

prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。
只有在Web应用中使用Spring时,该作用域才有效。

session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例,同样只有在Web应用中使用Spring时,该作用域才有效。

globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。
同样只有在Web应用中使用Spring时,该作用域才有效。

其中比较常用的是singleton和prototype两种作用域。
对于singleton作用域的Bean,每次请求该Bean都将获得相同的实例。
容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。
在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。
如果不指定Bean的作用域,Spring默认使用singleton作用域。
Java在创建Java实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。
因此,prototype作用域Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将Bean被设置成prototype作用域。


属性注入方式有哪三种?


set注入
构造注入
工厂注入


使用XML装配(xml是最常见的spring应用系统配置源)

几种spring容器都支持使用xml装配bean,包括:


1.XmlBeanFactory:调用InputStream载入上下文定义文件。

2.ClassPathXmlApplicationContext:从类路径载入上下文定义文件。

3.XmlWenApplicationContext:从web应用上下文中载入定义文件。


Spring中怎样实现自动扫描?


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


@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。
@Scope注解 作用域
@Lazy(true) 表示延迟初始化

@Service用于标注业务层组件、 

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件。

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Scope用于指定scope作用域的(用在类上)

@PostConstruct用于指定初始化方法(用在方法上)

@PreDestory用于指定销毁方法(用在方法上)

@Resource 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。

@DependsOn:定义Bean初始化及销毁时的顺序。
@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
@Autowired 默认按类型装配,如果我们想使用按名称装配,

@PostConstruct 初始化注解
@PreDestroy 摧毁注解默认单例启动就加载


静态代理和动态代理的关系


静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。

静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
 
动态代理是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的
 
业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。
 
还有一种动态代理 CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行
时,动态修改字节码达到修改类的目的。
 
AOP 编程就是基于动态代理实现的,比如著名的 Spring 框架、 Hibernate 框架等等都是动态代理的使用例子。


通知有哪几种类型,运行顺序是什么?


Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可。
AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值。
AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名,
来访问目标方法中所抛出的异常对象。
After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式。
Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint