(1) Annotation(注解方式)依赖额外的两个包 aspectjrt.jar aspectjweaver.jar
发现aspect,在以往的方式中通过配置xml文件来定义某个类具有某个特性。Annotation来指定这个类是切面
对 SecurityHandler 通过Annotation实现import org.aspectj.lang.annotaion.Aspect;
import org.aspectj.lang.annotation.PointCut;
import org.aspectj.lang.annotation.Before;
/**
* 定义这是一个切面
*
*/
@Aspect
public class SecurityHandler{
/**
*定义(切入点)PointCut 并且给这个方法取名为addAllMethod,这个方法只是一个表示,没有返回值和参数,
*存在的意义是要被重用的这个切入点的
*/
@PointCut("execution(* add*(..))")//这里支持表达式 第一个"*" 表示匹配任意的返回类型,".."表示任意
//多个参数。还支持与 或 非逻辑运算符,如:* add*(..)||* del*(..)
private addAllMethod(){}; /**
*定义advice 并且指定是before advice 还是Around 还是Throw
*/
@Before("addAllMethod()");//表明在执行jointPoint执行前执行
private void checkSecurity(){
//todo something
}}
//必须把这个切面注入IOC容器
<beans>
<!-- 启动多Annotation的支持-->
<aop:aspectj-autoproxy proxy-target-class="true"/>//proxy-target-class="true" 支持类的动态代理(CGLIB)
<bean id="securityHandler" class="cn.com.chenlly.SecurityHandler"/>//由于有注解,所以IOC容器知道这个是切面
<bean id="userManagerImpl" class="cn.com.chenlly.UserManagerImpl"/>
</benas>
Client:
public class Client{
....
//下面的factory 是一种查找注入的方法,区别于依赖注入。
BeanFactory factory = new ClassPathXmlApplication("applicationContext.xml");
UserManagerImpl userManagerImpl = factory.getBean("userManagerImpl");
//注意:这个工厂拿到的是个代理类
userManagerImpl.addUser();
}
(2) 采用静态的配置文件通过配置文件指定,那个是切面,那个pointCut 及advice
配置文件如下:<bean>
<bean id="securityHandler" class="cn.com.chenlly.SecurityHandler"/>//由于有注解,所以IOC容器知道这个是切面
<bean id="userManagerImpl" class="cn.com.chenlly.UserManagerImpl"/>
//配置aop
<aop:config>
<aop:aspect id="security" ref="securityHandler">//定义aspect
<aop:pointcut id="addAllMethod" expression="execution("*cn.com.chenlly.UserManagerImpl.add*(..)|| ")">//定义pointcut
<aop:before method="checkSecurity" pointcut-ref="addAllMethod"/>//定义advice 并且把这个advice应用到那个pointcut上
</aop:aspect>
</aop:config>
</benas>


(3)advice如何拿到调用方法的参数,就像在动态代理类里面的 []args,method在checkSecurity方法中加入JointPoint
import org.aspectj.lang.JointPoint;
private void checkSecurity(JointPoint jointPoint){
Object []obj = jointPoint.getArgs(); //得到参数列表
String method = jointPoint.getSignation().getName()//得到调用的方法 addUser
//todo something
}
总结:
如果目标对象实现了接口 默认情况下会使用动态代理实现AOP,也可以强制使用CGLIB
1)加入 CGLIB库
2)在配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
如果目标对象没有实现接口,就必须使用GCLIB,Spring 会自动在动态代理和CGLIB之间转换。
JDK动态代理和CGLIB的区别是
JDK动态代理只能是对实现了接口的类生产代理
CGLIB是针对类来生产代理,机制就是生产了一个子类,这个子类就是代理类,覆盖方法,因为是继承,所以属性和方法最好不要声明称final