两种切面的实现
package com.butch.a17;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
public class A17 {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("aspect1",Aspect1.class);
context.registerBean("config",config.class);
//加后置处理器
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
}
static class Targer1{
public void foo(){
System.out.println("target1 foo");
}
}
static class Targer2{
public void bar(){
System.out.println("target2 bar");
}
}
//aspect切面
@Aspect
static class Aspect1{
@Before("execution(* foo())")
public void before(){
System.out.println("aspect1 before.....");
}
@After("execution(* foo())")
public void after(){
System.out.println("aspect1 after.....");
}
}
//advisor切面
@Configuration
static class config{
@Bean
public Advisor advisor3(MethodInterceptor advice3){
AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression("execution(* foo())");
//第一个参数是切点 第二个参数是通知
return new DefaultPointcutAdvisor(aspectJExpressionPointcut,advice3);
}
@Bean
public MethodInterceptor advice3(){
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("advisor3 before.....");
Object proceed = methodInvocation.proceed();
System.out.println("advisor3 after.....");
return proceed;
}
};
}
}
}
代理创建器实现原理
AnnotationAwareAspectJAutoProxyCreator
这是一个bean后置处理器,即为AOP的实现原理
-
发现切面对象
-
高级切面转低级切面,创建代理
findEligibleAdvisors
-
有【资格】的 Advisor 一部分是低级的, 可以由自己编写, 如本例 A17 中的 advisor3
-
有【资格】的 Advisor 另一部分是高级的, 由解析 @Aspect 后获得
wrapIfNecessary
-
是否有必要创建的代理,它内部调用 findEligibleAdvisors, 只要返回集合不空, 则表示需要创建代理
-
它的调用时机通常在原始对象初始化后执行, 但碰到循环依赖会提前至依赖注入之前执行
总结
-
在容器中寻找目标类是否有匹配的切面,高级切面转化为低级
-
根据1返回的集合,不为空则创建代理对象
package org.springframework.aop.framework.autoproxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import java.util.List;
public class A17 {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("aspect1",Aspect1.class);
context.registerBean("config",config.class);
//加后置处理器
context.registerBean(ConfigurationClassPostProcessor.class);
//bean后处理器
//位置 bean 创建-> (*) 依赖注入 -> (*) 初始化
context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
context.refresh();
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
}
AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
// A17_1 a17_1 = new A17_1();
//第一个参数为目标类 找出目标类中有能使用增强的切面
List<Advisor> target1 = creator.findEligibleAdvisors(Targer1.class, "target1");
// List<Advisor> target1 = a17_1.findCandidateAdvisors(Targer1.class, "target1");
System.out.println("================================");
// for (Advisor advisor : target1) {
// System.out.println("advisor = " + advisor);
// }
Object o1 = creator.wrapIfNecessary(new Targer1(), "target1", "target1");
//o1为代理
System.out.println("o1.getClass() = " + o1.getClass());
//o2非代理
Object o2 = creator.wrapIfNecessary(new Targer2(), "target2", "target2");
System.out.println("o2.getClass() = " + o2.getClass());
}
static class Targer1{
public void foo(){
System.out.println("target1 foo");
}
}
static class Targer2{
public void bar(){
System.out.println("target2 bar");
}
}
//aspect切面
@Aspect
static class Aspect1{
@Before("execution(* foo())")
public void before(){
System.out.println("aspect1 before.....");
}
@After("execution(* foo())")
public void after(){
System.out.println("aspect1 after.....");
}
}
//advisor切面
@Configuration
static class config{
@Bean
public Advisor advisor3(MethodInterceptor advice3){
AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression("execution(* foo())");
//第一个参数是切点 第二个参数是通知
return new DefaultPointcutAdvisor(aspectJExpressionPointcut,advice3);
}
@Bean
public MethodInterceptor advice3(){
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("advisor3 before.....");
Object proceed = methodInvocation.proceed();
System.out.println("advisor3 after.....");
return proceed;
}
};
}
}
}
代理创建的时机
package org.springframework.aop.framework.autoproxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import javax.annotation.PostConstruct;
public class A17_1 {
public static void main(String[] args) {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean(Config.class);
//加后置处理器
context.registerBean(ConfigurationClassPostProcessor.class);
context.refresh();
context.close();
}
@Configuration
static class Config{
@Bean//代理创建器
public AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator(){
return new AnnotationAwareAspectJAutoProxyCreator();
}
@Bean//处理@autowired注解
public AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor(){
return new AutowiredAnnotationBeanPostProcessor();
}
@Bean//处理@postconstruct、
public CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor(){
return new CommonAnnotationBeanPostProcessor();
}
@Bean//切面
public Advisor advisor(MethodInterceptor advice3){
AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression("execution(* foo())");
//第一个参数是切点 第二个参数是通知
return new DefaultPointcutAdvisor(aspectJExpressionPointcut,advice3);
}
@Bean//通知
public MethodInterceptor advice3(){
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("advisor3 before.....");
Object proceed = methodInvocation.proceed();
System.out.println("advisor3 after.....");
return proceed;
}
};
}
@Bean
public Bean1 bean1(){
return new Bean1();
}
@Bean
public Bean2 bean2(){
return new Bean2();
}
}
static class Bean1 {
public void foo() {
}
public Bean1() {
System.out.println("bean1实例化构造方法........");
}
@PostConstruct
public void init() {
System.out.println("bean1的初始化init方法................");
}
}
static class Bean2 {
@Autowired
public void setBean1(Bean1 bean1){
System.out.println("bean2依赖注入bean1..................." + bean1.getClass());
}
public Bean2() {
System.out.println("bean2实例化构造方法........");
}
@PostConstruct
public void init() {
System.out.println("bean2的初始化init方法................");
}
}
}
bean2依赖bean1的时候,并且bean1也依赖于bean2,即为循环依赖,bean1中有需要增强的方法,代理对象则是在bean1初始化之后创建,bea2则注入bea1的代理对象
-
bean1构造
-
注入bean2,bean2没有,暂停进入bean2生命周期
-
bean2实例化方法
-
bean2依赖注入bean1,由于bean1中的方法需要增强,因此需要注入代理对象,在bean实例化后,创建bean1的代理对象
-
bean2的初始化
-
bean1的依赖注入
-
bean1的初始化
总结
-
无循环依赖代理创建在初始化之后
-
有循环依赖时 创建于的实例化之后依赖注入之前,并且存于二级缓存中
-
依赖注入及初始化阶段不应增强,如set方法应该调用原始方法的set
高级切面转低级切面
共五种通知类型,在findEligibleAdvisors 方法中,转换为对应低级切面
-
@Before 前置通知会被转换为原始的 AspectJMethodBeforeAdvice 形式, 该对象包含了如下信息
-
通知代码从哪儿来
-
切点是什么
-
通知对象如何创建, 本例共用同一个 Aspect 对象
-
-
类似的还有
-
AspectJAroundAdvice (环绕通知)
-
AspectJAfterReturningAdvice
-
AspectJAfterThrowingAdvice (环绕通知)
-
AspectJAfterAdvice (环绕通知)
-
package org.springframework.aop.framework.autoproxy;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectInstanceFactory;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class A18 {
public static void main(String[] args) {
AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new Aspect());
List<Advisor> list = new ArrayList<>();
for (Method declaredMethod : Aspect.class.getDeclaredMethods()) {
if (declaredMethod.isAnnotationPresent(Before.class)) {
//解析切点
String value = declaredMethod.getAnnotation(Before.class).value();
AspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();
aspectJExpressionPointcut.setExpression(value);
//转为对应底层通知类
AspectJMethodBeforeAdvice aspectJMethodBeforeAdvice = new AspectJMethodBeforeAdvice(declaredMethod,aspectJExpressionPointcut,factory);
//转为低级切面
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(aspectJExpressionPointcut, aspectJMethodBeforeAdvice);
list.add(defaultPointcutAdvisor);
}
}
for (Advisor advisor : list) {
System.out.println("advisor = " + advisor);
}
}
static class Aspect{
@Before("execution(* foo")
public void before1() {
System.out.println("===========before1========");
}
@Before("execution(* foo")
public void before2() {
System.out.println("===========before2========");
}
}
static class Target{
public void foo(){
System.out.println("target foo===============");
}
}
}
总结:
-
拿到高级切面类,通过反射获取所有的方法
-
检查方法上是否包含通知类型的注解
-
解析注解的切点表达式,设置底层的切点对象
-
根据不同通知类型注解实现对应底层通知的实现,最终都是转化为环绕通知类型
-
通过通知和切点实现底层切面