AOP:在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP代理对象:
在使用权限拦截的时候,web中可以使用过滤器来实现,也可以使用AOP,控制代理对象来控制目标对象的方法,在使用代理对象,一般有两种方式:
1.静态代理
2.动态代理
下面介绍动态代理的原理:
① 创建一个代理简单的代理工厂:
package com.heying.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.heying.service.impl.PersonServiceBean;
/** * 这是一个简单的动态代理,要求工厂类实现InvocationHandler接口<br> * Proxy类会回调InvocationHandler接口中的invoke方法,实现权限拦截 * @author Heying_He * */
public class JDKProxyFactory implements InvocationHandler {
private Object targeObject;
public Object createProxyintance(Object targeObject){
this.targeObject = targeObject;
// 目标对象的classload,目标对象的所有接口
//(代理类的类装载器,代理类的所有接口,回调对象)
return Proxy.newProxyInstance(this.targeObject.getClass().getClassLoader(),
this.targeObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if( ((PersonServiceBean) this.targeObject).getUser() != null ){
return method.invoke(targeObject, args);
}
return null;
}
}
②编写一个业务接口,注意的是要求接口必须有实现类,且要使用面向接口编程实现代理对象,没有接口的情况下,需要其他的方式,使用接口编程是一个良好的习惯:
创建简单业务接口:
package com.heying.service;
public interface PersonService {
public void save(String name);
public void update(String name,Integer personId);
public String getPersonName(Integer personId);
}
简单业务接口的实现:
package com.heying.service.impl;
import com.heying.service.PersonService;
public class PersonServiceBean implements PersonService {
private String user = null;
public PersonServiceBean() {}
public PersonServiceBean(String user) {
this.user = user;
}
@Override
public String getPersonName(Integer personId) {
return String.valueOf(personId);
}
@Override
public void save(String name) {
System.out.println("save==function: "+name);
}
@Override
public void update(String name, Integer personId) {
System.out.println("update==function: "+personId);
}
public String getUser() {
return user;
}
}
测试:
第一步使用一个默认构造器的对象初始化,user对象为null,在代理的回调方法中已经拦截了user=null的情况:
@Test
public void proxytest(){
JDKProxyFactory factory = new JDKProxyFactory();
PersonService personService = (PersonService) factory.createProxyintance(new PersonServiceBean());
personService.save("heying");
personService.getPersonName(Integer.valueOf(110));
personService.update("heying123", Integer.valueOf(1));
}
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
结果:
第二部,使用带user参数的构造器初始化,user对象不为null
@Test
public void proxytest(){
JDKProxyFactory factory = new JDKProxyFactory();
PersonService personService = (PersonService) factory.createProxyintance(new PersonServiceBean("xxx"));
personService.save("heying");
personService.getPersonName(Integer.valueOf(110));
personService.update("heying123", Integer.valueOf(1));
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
}
结果:
使用cglib实现代理:
package com.heying.aop;
import java.lang.reflect.Method;
import com.heying.service.impl.PersonServiceBean;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGlibProxyFactory implements MethodInterceptor {
private Object targeObject;
public Object createProxyintance(Object targeObject){
this.targeObject = targeObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.targeObject.getClass()); // 覆盖所有非Final方法的children
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object object, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {
if( ((PersonServiceBean) this.targeObject).getUser() != null ){
return method.invoke(targeObject, args);
}
return null;
}
}
AOP中的几个概念:
Aspect(切面):指横切性关注点为切面,与类相识,关注点不同,类是对物体特征的抽象,切面是横切性关注点的抽象。
Joinpoint(连接点):所谓连接点是指被拦截的点,在spring中一般是方法
Pointcut(切入点):所谓切入点指我们对joinpoint的拦截的定义
Advice(通知):所谓通知是指拦截到joinpoint的之后做的事情,分为前置,后置,异常,最终,环绕通知。
Target(目标对象):代理的目标对象
Weave(织入):将aspects应用到targe对象并导致proxy对象创建的过程为织入
Tntroduction(引入):在不修改类代码的情况下,Tntroduction可以在运行期为类动态的添加一些方法或者Field