AOP都知道,是spring中的面向切面编程,就是可以把我们写的代码横向扩展,而且又不会影响原来的代码结构,是一种思想。说白了就是可以在你想实现什么功能的前后能够搞一些事情。底层使用的是JDK和Cglib动态代理
为什么要使用AOP呢:
1、AOP采用了横向的抽取机制,取代了传统纵向继承体系重复性代码结构
2、可以在不修改源代码的前提下,对程序功能进行增强
主要的几种的方式:
1、前置通知:@Before 在我们执行目标方法前运行
2、后置通知:@After 在我们目标方法运行之后运行,不管有没有异常
3、后置返回通知:@AfterReturning 在我们的目标方法正常返回值之后运行
4、异常通知:@AfterThrowing 在我们执行目标方法出现异常之后运行
5、环绕通知:@Around 前置 > @Before +后置 < @After(正常) 动态代理,必须手动执行目标方法
注解实现AOP
先创建一个Service和接口类
public interface UserService {
public String selectUserName();
}
@Service("userService")
public class UserServiceImp implements UserService {
@Override
public String selectUserName() {
String name = "zx";
return name;
}
}
创建实体类
public class UserEntity {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建一个控制层
@RestController
@RequestMapping("/aop")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/aoptest")
public void UserTest(){
System.out.println("UserServiceImp方法");
userService.selectUserName();
}
}
创建代理的配置类。把bean注入到容器中
@Configuration
@EnableAspectJAutoProxy
public class UserConfig{
/**
* 把目标类注册到spring容器中去
* @return
*/
@Bean
public UserService userService(){
return new UserService() {
@Override
public String selectUserName() {
String name = "配置类实例";
return name;
}
};
}
/**
* 注册切面类到spring容器中去
* @return
*/
@Bean
public UserPointCut servantAspects02(){
return new UserPointCut();
}
}
再创建一个切面类
@Aspect
@Component
public class UserPointCut {
@Pointcut("execution(* com.zx.springaop.service..*(..))")
public void UserPointCut(){}
@Before("UserPointCut()")
public void BeforUser(){
System.out.println("前置");
}
@After("UserPointCut()")
public void AfterUser(){
System.out.println("后置");
}
@AfterReturning("UserPointCut()")
public void AfterReturning(){
System.out.println("后置返回");
}
@AfterThrowing(value = "UserPointCut()",throwing = "ex")
public void AfterThreadExction(Exception ex){
System.out.println("后置异常抛出"+ex);
}
@Around("UserPointCut()")
public Object AroudUserCut(ProceedingJoinPoint pjd) {
Object result=null;
String methodName=pjd.getSignature().getName();//方法名
try {
//前置通知
System.out.println("the method "+methodName+" begins with "+Arrays.asList(pjd.getArgs()));
result=pjd.proceed();
//结果通知
System.out.println("the method"+methodName+" ends "+result);
} catch (Throwable e) {
//异常通知
System.out.println("the method "+methodName+" occurs execption:"+e);
throw new RuntimeException(e);
}
//后置通知
System.out.println("the method "+methodName+" ends");
return result;
}
}
最后创建一个测试类
public class UserPointCutTest {
public static void main(String args[]){
AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(UserConfig.class);
UserService userService = (UserService) acc.getBean(UserService.class);
userService.selectUserName();
}
}
输出:
——————————————————————————————
下面开始分析。
打断点,看debug模式,
可以看到现在是JDK的动态代理模式,那么怎么可以转变成CGLib呢,
状态改为true就是强制使用CGLib动态代理了。说白了就是把有没有接口。有接口就是JDK,没有就默认CGLib
流程分析:
将bean导入spring容器AspectJAutoProxyRegistrar->ImportBeanDefinitionRegistrar#registerBeanDefinitions
将bean注册到spring容器 AnnotationAwareAspectJAutoProxyCreator className: org.springframework.aop.config.internalAutoProxyCreator class: 根据spring提供的规范构建spring bean RootBeanDefinition
上面构建 AnnotationAwareAspectJAutoProxyCreator 这个bean 然后这个bean实现InstantiationAwareBeanPostProcessor接口
该接口实现BeanPostProcessor接口 BeanPostProcessor是spring提供的扩展接口 在bean实例的时候回调 --》postProcessAfterInitialization
然后就会找所有的Advisor
1、 第一步: 先找父类时候有实现Advisor的接口。
2、 第二步: 然后找到所有类上面注解标注为@Aspect, 然后解析该类标注Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
AOP的 实现方式很简单,就是动态代理。就是在实例化的时候生成代理类,来替换掉真实实现类来对外提供服务。就是在getBean(…)的时候返回的其实是代理类的一个实例,而这个代理类就是JDK活着CGLib动态生成的,(spring-aop只能在Spring中才能实现。)
先看一下 DefaultAdvisorAutoProxyCreator类中的BeanPostProcessor方法。在IOC中,这个方法是在init-method前后执行的。
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
回顾一下IOC:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 1. 创建实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
...
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 2. 装载属性
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 3. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
...
}
在第三步,初始化Bean,会调用BeanPostProcessor()方法
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 1. 执行每一个 BeanPostProcessor 的 postProcessBeforeInitialization 方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用 bean 配置中的 init-method="xxx"
invokeInitMethods(beanName, wrappedBean, mbd);
}
...
if (mbd == null || !mbd.isSynthetic()) {
// 我们关注的重点是这里!!!
// 2. 执行每一个 BeanPostProcessor 的 postProcessAfterInitialization 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
也就是说,Spring AOP 会在 IOC 容器创建 bean 实例的最后对 bean 进行处理。其实就是在这一步进行代理增强。
DefaultAdvisorAutoProxyCreator 的继承结构中,postProcessAfterInitialization() 方法在其父类 AbstractAutoProxyCreator 这一层被覆写了:
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
看wrapifnecessary方法。会返回一个代理类
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 返回匹配当前 bean 的所有的 advisor、advice、interceptor
// 对于本文的例子,"userServiceImpl" 和 "OrderServiceImpl" 这两个 bean 创建过程中,
// 到这边的时候都会返回两个 advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理...创建代理...创建代理...
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
在看 createProxy(…)方法,创建代理类:
// 注意看这个方法的几个参数,
// 第三个参数携带了所有的 advisors
// 第四个参数 targetSource 携带了真实实现的信息
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建 ProxyFactory 实例
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 在 schema-based 的配置方式中,我们介绍过,如果希望使用 CGLIB 来代理接口,可以配置
// proxy-target-class="true",这样不管有没有接口,都使用 CGLIB 来生成代理:
// <aop:config proxy-target-class="true">......</aop:config>
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 点进去稍微看一下代码就知道了,主要就两句:
// 1. 有接口的,调用一次或多次:proxyFactory.addInterface(ifc);
// 2. 没有接口的,调用:proxyFactory.setProxyTargetClass(true);
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 这个方法会返回匹配了当前 bean 的 advisors 数组
// 对于本文的例子,"userServiceImpl" 和 "OrderServiceImpl" 到这边的时候都会返回两个 advisor
// 注意:如果 specificInterceptors 中有 advice 和 interceptor,它们也会被包装成 advisor,进去看下源码就清楚了
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
这个方法主要是在内部创建了一个 ProxyFactory 的实例,然后 set 了一大堆内容,剩下的工作就都是这个 ProxyFactory 实例的了,通过这个实例来创建代理: getProxy(classLoader)。
看看代理类
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
通过创建代理类来生成aop代理
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
创建 AopProxy 之前,我们需要一个 AopProxyFactory 实例,然后看 ProxyCreatorSupport 的构造方法:
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
看DefaultAopProxyFactory 这个类,我们看它的 createAopProxy(…) 方法:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// (我也没用过这个optimize,默认false) || (proxy-target-class=true) || (没有接口)
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果要代理的类本身就是接口,也会用 JDK 动态代理
// 我也没用过这个。。。
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
// 如果有接口,会跑到这个分支
return new JdkDynamicAopProxy(config);
}
}
// 判断是否有实现自定义的接口
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
这就有可能返回jdk,也有可能返回cglib,然后下面就分别是jdk和cglib的源码,最后各自集成各自的拦截类,进行代理