提交 bbce0776 编写于 作者: 希川's avatar 希川

<feat>: 将AOP代理功能集成进管理容器中

上级 b2c9e023
......@@ -9,6 +9,9 @@ import org.aopalliance.intercept.MethodInterceptor;
* @Date 2021/11/3 14:46
*/
public class AdvisedSupport {
private boolean proxyTargetClass = false;
// 被代理的目标对象
private TargetSource targetSource;
// 方法拦截器
......@@ -16,6 +19,14 @@ public class AdvisedSupport {
// 方法匹配器(检查目标方法是否符合通知条件)
private MethodMatcher methodMatcher;
public boolean isProxyTargetClass() {
return proxyTargetClass;
}
public void setProxyTargetClass(boolean proxyTargetClass) {
this.proxyTargetClass = proxyTargetClass;
}
public TargetSource getTargetSource() {
return targetSource;
}
......
package cn.noexception.container.aop;
import org.aopalliance.aop.Advice;
/**
* Advisor
* 定义访问者
* <p>
* Advisor 承担了 Pointcut 和 Advice 的组合,
* Pointcut 用于获取 JoinPoint,而 Advice 决定于 JointPoint 执行什么操作
* </p>
* @author 吕滔
* @Date 2021/11/4 16:17
*/
public interface Advisor {
Advice getAdvice();
}
package cn.noexception.container.aop;
import org.aopalliance.aop.Advice;
/**
* BeforeAdvice
*
* @author 吕滔
* @Date 2021/11/4 15:18
*/
public interface BeforeAdvice extends Advice {
}
package cn.noexception.container.aop;
import java.lang.reflect.Method;
/**
* MethodBeforeAdvice
*
* @author 吕滔
* @Date 2021/11/4 16:07
*/
public interface MethodBeforeAdvice extends BeforeAdvice{
/**
* 给定方法调用之前的回调
*/
void before(Method method, Object[] args, Object target) throws Throwable;
}
package cn.noexception.container.aop;
/**
* PointcutAdvisor
*
* @author 吕滔
* @Date 2021/11/4 16:27
*/
public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
}
package cn.noexception.container.aop.aspectj;
import cn.noexception.container.aop.Pointcut;
import cn.noexception.container.aop.PointcutAdvisor;
import org.aopalliance.aop.Advice;
/**
* AspectJExpressionPointcutAdvisor
* <p>
* 实现了 PointcutAdvisor 接口,把切面、拦截方法和具体拦截表达式包装在一起。</br>
* 这样就可以在 xml 的配置中定义一个 pointcutAdvisor 切面拦截器了。
* </p>
*
* @author 吕滔
* @Date 2021/11/4 16:30
*/
public class AspectJExpressionPointcutAdvisor implements PointcutAdvisor {
// 切面
private AspectJExpressionPointcut pointcut;
// 具体的拦截方法
private Advice advice;
// 表达式
private String expression;
public String getExpression() {
return expression;
}
public void setAdvice(Advice advice) {
this.advice = advice;
}
@Override
public Advice getAdvice() {
return advice;
}
@Override
public Pointcut getPointcut() {
if (null == pointcut) {
pointcut = new AspectJExpressionPointcut(expression);
}
return pointcut;
}
}
package cn.noexception.container.aop.framework;
import cn.noexception.container.aop.AdvisedSupport;
/**
* ProxyFactory<p>
* - 代理工厂类,用于解决关于选择Cglib 和 JDK 两种代理的问题<p>
* - 有了代理工厂就可以安札不同的创建需求进行控制
*
* @author 吕滔
* @Date 2021/11/4 16:43
*/
public class ProxyFactory {
private AdvisedSupport advisedSupport;
public ProxyFactory(AdvisedSupport advisedSupport) {
this.advisedSupport = advisedSupport;
}
public Object getProxy() {
return createAopProxy().getProxy();
}
private AopProxy createAopProxy() {
if (advisedSupport.isProxyTargetClass()) {
return new Cglib2AopProxy(advisedSupport);
}
return new JdkDynamicAopProxy(advisedSupport);
}
}
package cn.noexception.container.aop.framework.adapter;
import cn.noexception.container.aop.MethodBeforeAdvice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* MethodBeforeAdviceInterceptor
* - 方法拦截器
* @author 吕滔
* @Date 2021/11/4 16:34
*/
public class MethodBeforeAdviceInterceptor implements MethodInterceptor {
private MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}
/**
* 实现了 MethodInterceptor 接口,调用 advice 中的 before 方法,传入对应的参数信息。
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
this.advice.before(invocation.getMethod(), invocation.getArguments(), invocation.getThis());
return invocation.proceed();
}
}
package cn.noexception.container.aop.framework.autoproxy;
import cn.noexception.container.BeansException;
import cn.noexception.container.aop.*;
import cn.noexception.container.aop.aspectj.AspectJExpressionPointcutAdvisor;
import cn.noexception.container.aop.framework.ProxyFactory;
import cn.noexception.container.factory.BeanFactory;
import cn.noexception.container.factory.BeanFactoryAware;
import cn.noexception.container.factory.config.InstantiationAwareBeanPostProcessor;
import cn.noexception.container.factory.support.DefaultListableBeanFactory;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
/**
* DefaultAdvisorAutoProxyCreator
* <p>加入 Bean 生命周期的自动代理创建者</p>
*
* @author 吕滔
* @Date 2021/11/4 16:53
*/
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {
private DefaultListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (isInfrastructureClass(beanClass)) return null;
Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();
for (AspectJExpressionPointcutAdvisor advisor : advisors) {
ClassFilter classFilter = advisor.getPointcut().getClassFilter();
if (!classFilter.matches(beanClass))
continue;
AdvisedSupport advisedSupport = new AdvisedSupport();
TargetSource targetSource = null;
try {
targetSource = new TargetSource(beanClass.getDeclaredConstructor().newInstance());
} catch (Exception e) {
e.printStackTrace();
}
// 设置目标对象
advisedSupport.setTargetSource(targetSource);
// 设置拦截方法
advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
// 设置匹配器
advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
// 设置选择使用的代理方法
advisedSupport.setProxyTargetClass(false);
return new ProxyFactory(advisedSupport).getProxy();
}
return null;
}
/**
* 检测/感知 bean 是否是切点 <p>按需拦截
*/
private boolean isInfrastructureClass(Class<?> beanClass) {
return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);
}
}
package cn.noexception.container.factory.config;
import cn.noexception.container.BeansException;
/**
* InstantiationAwareBeanPostProcessor
*
* @author 吕滔
* @Date 2021/11/4 16:55
*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* 在 Bean 对象执行初始化方法之前,执行此方法
*/
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
}
......@@ -71,4 +71,12 @@ public class ApiRunner {
// 测试调用
System.out.println("测试结果:"+proxy_cglib.register("感冒灵"));
}
@Test
public void test_aop(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:config_aop.xml");
IUserService userService = applicationContext.getBean("userService", IUserService.class);
System.out.println("测试结果:"+userService.queryUserInfo());
}
}
package cn.noexception.test.bean;
import cn.noexception.container.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* UserServiceBeforeAdvice
*
* @author 吕滔
* @Date 2021/11/4 17:30
*/
public class UserServiceBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("拦截方法:" + method.getName());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userService" class="cn.noexception.test.bean.UserService"/>
<bean class="cn.noexception.container.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean id="beforeAdvice" class="cn.noexception.test.bean.UserServiceBeforeAdvice"/>
<bean id="methodInterceptor" class="cn.noexception.container.aop.framework.adapter.MethodBeforeAdviceInterceptor">
<property name="advice" ref="beforeAdvice"/>
</bean>
<bean id="pointcutAdvisor" class="cn.noexception.container.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="expression" value="execution(* cn.noexception.test.bean.IUserService.*(..))"/>
<property name="advice" ref="methodInterceptor"/>
</bean>
</beans>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册