您的位置:首页 > 编程语言 > Java开发

【Spring之AOP】

2016-05-02 13:09 429 查看
什么是AOP?

-面向切面编程

-它是一种思想,可在不改变程序源码的情况下为程序添加额外的功能。

-允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发。应用对象只实现业务逻辑即可,并不负责其他的系统级关注点。

-AOP专门用于处理系统中分布于各个模块中的交叉关注点的问题,在J2EE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常常用的解决方案。

AOP的发展过程?

-静态AOP:Aspect形式,通过特定的编译器,将实现后的Aspect编译并织入到系统的静态类中

-动态AOP:AOP的织入过程在系统运行开始之后进行,而不是预先编译到系统中

AOP术语?

-连接点:程序执行的某个特定位置,比如类初始化前、类初始化后、方法调用前、方法调用后等

-切点:通过切点来定位特定的连接点

-增强:织入到目标类连接点上的一段程序代码

-目标对象:增强逻辑的织入目标类

-引介:是一种特殊的增强,它为类添加一些属性和方法

-织入:为增强添加目标类的具体连接点上的过程

-代理:一个类被AOP织入增强后,会产生一个结果类,该类融合了原类和增强逻辑的代理类

-切面:由切点和增强组成,既包括了横切逻辑的定义,也包括了连接点的定义

AOP的原理剖析?

-AOP代理其实是由AOP框架动态生成的一个对象,该对象可作为目标对象使用,AOP代理所包含的方法与目标对象的方法如下图所示:



使用AOP的步骤是:

定义普通业务组件 ---> 定义切入点 ---> 定义增强处理

代理对象的方法 = 增强处理 + 被代理对象的方法

AOP的通俗理解?

-一个组件A,不关心其他常用的服务组件B,但是这个组件A使用组件B的时候,不是组件A自身去调用,而是通过配置等其他方式,比如Spring中可以通过xml配置文件。这样就使得A压根就不需要知道服务组件B是怎样的,爱存在不存在,爱怎么存在都与A无关。A只关心自己的业务逻辑,具体A使用B的时候,配置文件去做,与具体的A组件无关。

AOP的实现方法?

(1)利用Proxy实现AOP功能 (JDK动态代理)

采用Proxy类方法,基本流程为:主函数--->代理--->目标对象的方法。对于Proxy类有一个使用前提,就是目标对象必须实现接口,否则不能使用这个方法。

实现AOP功能步骤如下:

创建接口:StudentInterface.java

创建接口实现类:StudentBean.java

创建代理工厂:ProxyFactory.java

public interface StudentInterface {

public void print();

}


public class StudentBean implements StudentInterface {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public StudentBean() {
}

public StudentBean(String name) {
super();
this.name = name;
}

@Override
public void print() {
System.out.println("hi student.");
}

}


public class ProxyFactory implements InvocationHandler {

private Object object;

public Object createStudentProxy(Object obj) {
this.object = obj;
//创建并返回代理
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
StudentBean studentBean = (StudentBean) object;
Object obj = null;
if(studentBean.getName() != null){
obj = method.invoke(object, args);
}else{
System.out.println("学生姓名为空,代理类已经进行拦截.");
}
return obj;
}

}


public class Test001 {

public static void main(String[] args) {
StudentInterface s1 = new StudentBean();
ProxyFactory proxyFactory = new ProxyFactory();
StudentInterface s2 = (StudentInterface) proxyFactory
.createStudentProxy(s1);
s2.print();
}
}


总结:
目标对象必须实现接口

返回创建的代理对象

重写invoke()方法

限制条件放在invoke()方法中

(2)利用CGLIB实现AOP功能(CGLIB动态代理)

CGLIB(code generation library)是一个开源项目,它是一个强大的、高性能、高质量的code生成类库,它可以在运行期间扩展Java类和实现Java接口。

实现AOP功能步骤如下所示:

引入jar包

创建实体类

创建CGLIB代理类

创建入口类进行测试

public class StudentBean {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public StudentBean() {
}

public StudentBean(String name) {
super();
this.name = name;
}

public void print() {
System.out.println("hi student.");
}

}


public class CGLIBProxyFactory implements MethodInterceptor{

private Object object;

public Object createStudentProxy(Object obj){
this.object = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
return enhancer.create();
}

@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
StudentBean stu  = (StudentBean) object;
Object ret = null;
if(stu.getName() != null){
methodProxy.invoke(object, args);
}else{
System.out.println("学生姓名为空,方法已经被拦截.");
}
return ret;
}

}


public class Test002 {

public static void main(String[] args) {

StudentBean s1 = new StudentBean();
CGLIBProxyFactory cglibProxyFactory = new CGLIBProxyFactory();
StudentBean s2 = (StudentBean) cglibProxyFactory.createStudentProxy(s1);
s2.print();

}

}


(3)利用Spring XML文件配置方式实现AOP功能步骤如下:

引入jar包

配置AOP命名空间

创建目标对象类

创建切面

在配置文件中配置

创建入口类进行测试

public interface TrainStationAware {

//售票方法
public String sellTicket(String name);

//退票方法
public String returnTicket(String name);
}


public class TrainStation implements TrainStationAware{

@Override
public String sellTicket(String name) {
System.out.println(name + "购票成功");
return "ok";

}

@Override
public String returnTicket(String name) {
System.out.println(name + "退票成功");
return "ok2";
}

}


public class XmlAdvice {

/**
* 在核心业务执行前执行,不能阻止核心业务的调用。
*
* @param joinPoint
*/
private void doBefore(JoinPoint joinPoint) {
System.out.println("-----doBefore().invoke-----");
}

/**
* 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
*
* 注意:当核心业务抛异常后,立即退出,转向After Advice 执行完毕After Advice,再转到Throwing Advice
*
* @param pjp
* @return
* @throws Throwable
*/
private Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("-----doAround().invoke-----");
MethodSignature ms = (MethodSignature) pjp.getSignature();
Method method = ms.getMethod();
Object retVal = null;
if("returnTicket".equals(method.getName())){
System.out.println("代理售票点不能办理退票");
}else{
retVal = pjp.proceed();
}

System.out.println("-----End of doAround()------");
return retVal;
}

/**
* 核心业务逻辑退出后(包括正常执行结束和异常退出),执行此Advice
*
* @param joinPoint
*/
private void doAfter(JoinPoint joinPoint) {
System.out.println("-----doAfter().invoke-----");
}

/**
* 核心业务逻辑调用正常退出后,不管是否有返回值,正常退出后,均执行此Advice
*
* @param joinPoint
*/
private void doReturn(JoinPoint joinPoint) {
System.out.println("-----doReturn().invoke-----");
}

/**
* 核心业务逻辑调用异常退出后,执行此Advice,处理错误信息
*
* @param joinPoint
* @param ex
*/
private void doThrowing(JoinPoint joinPoint, Throwable ex) {
System.out.println("-----doThrowing().invoke-----");
System.out.println(" 错误信息:" + ex.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> 
<bean id="trainStationAware" class="com.bear.spring.aop.TrainStation"/>

<bean id="xmlHandler" class="com.bear.spring.aop.XmlAdvice" />

<aop:config>
<aop:aspect id="aspect" ref="xmlHandler">
<aop:pointcut id="pointUserMgr" expression="execution(* com.bear.spring.aop.*.*Ticket(..))"/>
<aop:before method="doBefore"  pointcut-ref="pointUserMgr"/>
<aop:after method="doAfter"  pointcut-ref="pointUserMgr"/>
<aop:around method="doAround"  pointcut-ref="pointUserMgr"/>
<aop:after-returning method="doReturn"  pointcut-ref="pointUserMgr"/>
<aop:after-throwing method="doThrowing" throwing="ex" pointcut-ref="pointUserMgr"/>

</aop:aspect>
</aop:config>
</beans>


@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
TrainStationAware tsa = (TrainStationAware) context.getBean("trainStationAware");

tsa.sellTicket("张三");
//		tsa.returnTicket("李四");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: