他做每一件小事都像救命稻草一样紧紧抓住,等到有一天我一看,嚯,好家伙,他抱住的已经是可以让我仰望的参天大树了 <士兵突击>
1.静态代理与JDK动态代理与CGLB动态代理2.AOP体系2.1 基础概念的理解2.2 Spring提供操作组件2.2.1.提建议2.2.2.寻找建议者2.2.3.代理的创建时机2.2.4.代理的创建2.2.5.代理的执行3.总结
有一天:领导建议我们给删除操作方法添加操作日志。
为了完成这个意愿,AOP为此做了多少工作呢??
这一切的一切,都要从代理说起
1.静态代理与JDK动态代理与CGLB动态代理
1.静态代理:
- 硬编码静态代理: 说白了就是通过编码上的设计达到代理的效果。
- AspectJ编译织入 :编译期把内容编译到字节码中,
重点:编译期把内容织入代理对象
2.动态代理:通过动态生成新的类字节码,来达到动态代理的目标
- JDK动态代理:Proxy+InvocationHandler 模式
- CGLB动态代理: Enhancer + MethodInterceptor(CallBack)
重点:生成了新的字节码,动态代理
具体可阅读我的静态代理与JDK动态代理与CGLIB动态代理
2.AOP体系
2.1 基础概念的理解
再来重温这句话领导建议给删除操作方法添加操作日志
这里面包含的点:
谁提的
:领导给谁提的
:删除操作提的什么建议
:添加操作日志
至此引出了三个接口出来:
Advisor
: 提建议者Pointcut
:切点,给哪一类人提建议Advise
:建议,通知(建议的内容)
当然这里面还有几个隐藏的角色,AOP体系也有对应的定义:
TargetSource
: 目标对象Joinpoint
:连接点,当领导提到建议具体到某个方法上时,Joinpoint就是那个方法的信息封装体。在Joinpoint
中我们可以获取到目标方法的相关信息Advised
:当一个人被建议成功后,他就可以看做一个Advised
他们之间的关系:
- Advisor= Pointcut + Advise
- Advised = N * Advisor :一个人可能被多个 建议者建议。
这几个概念就组成了AOP体系的整体概念框架。
此时:我们达成一个共识,
- 当我在做AOP编程的时候,其实就是一个提建议的过程。
- 当给目标对象提了有效建议会为其创建代理
2.2 Spring提供操作组件
有了规范的指导,剩下的就是实现规范,Spring提供了哪些东西呢?
以我们最熟悉的切面编程为例,事务,来看看AOP体系的运作过程.
2.2.1.提建议
切面,事务本质都是提建议。例如下面,我给
cn.wqd.aop
包下的方法提了日志记录的建议,事务是给方法提了事务控制的建议
(1.切面
@Aspect @Component public class WebLogAcpect { private Logger logger = LoggerFactory.getLogger(WebLogAcpect.class); //定义切入点,切入点为com.example.aop下的所有函数 @Pointcut("execution(public * cn.wqd.aop..*.*(..))") public void webLog(){} @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { System.out.println("这里是AOP前置方法"); } }
(2.事务
Service public class TransactionalService { @Autowired DataSource dataSource; @Autowired UserDao userDao; @Transactional public String save(){ System.out.println("被事务方法"); User user = new User("被事务方法",1); Map<Object, Object> map = TransactionSynchronizationManager.getResourceMap(); System.out.println(userDao.getClass().getName());// userDao.save(user); return "save"; }
如何使用AOP是我们最熟悉的,但是他们又和上面的角色有啥关系呢?别急往下看
2.2.2.寻找建议者
提了建议,Spring如何知道是否有提建议者。
(1.BeanFactoryAdvisorRetrievalHelper
为了把应用中的那些建议者找出来,Spring首先提供了一个BeanFactoryAdvisorRetrievalHelper
,建议者检索工具:目的是识别出那些实现了Advisor接口的
的建议者,并把他们注册成一个Bean,并缓存起来。
public class BeanFactoryAdvisorRetrievalHelper { public List<Advisor> findAdvisorBeans() { (1) advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); (2) this.cachedAdvisorBeanNames = advisorNames; (3) advisors.add(this.beanFactory.getBean(name, Advisor.class)); } }
检索逻辑:找到所有实现了Advisor
的Beandefiniton;缓存他们的beanName;调用Bean创建逻辑,创建一个Bean出来。
直接实现
Advisor
接口,显示的表明自己就是一个建议者。
但是平时我们开发并不是用这种直接实现Advisor
的方式。@Aspect
注解,事务才是我们常用的。那他们到底是不是建议者呢?
(2.@Aspect
切面建议者
BeanFactoryAspectJAdvisorsBuilder
把@Aspect
注解的类的建议读取出来,Spring为此提供了一个建议者构建工具BeanFactoryAspectJAdvisorsBuilder
Aspect建议者构建器。
从其名字直译:他是一个专门构建Aspect建议者的Bean的工具
private final AspectJAdvisorFactory advisorFactory; public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) { this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory)); }
通过其构造方法,我们发现他默认会创建一个ReflectiveAspectJAdvisorFactory
,从其名字可以看出,他是通过反射的机制来工作的。BeanFactoryAspectJAdvisorsBuilder
的大部分工作其实就是由ReflectiveAspectJAdvisorFactory
完成的。