学习Spring第五天
BeanNameAutoProxyCreator
生产中会有会多bean需要代理,为了节约时间和减少工作量,我们可以使用自动代理来创建代理Bean
个人感觉十分简单
首先创建一个BeanNameAutoProxyCreator的Bean,然后把Advisor和需要代理的Bean丢进去(支持正则匹配)
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>customerPointCut</value>
<value>customerAdvisor</value>
</list>
</property>
</bean>
然后测试类不需要在调用Proxy的名字,直接使用,Spring会自动创建代理
DefaultAdvisorAutoProxyCreator
听说十分强大,如果有Bean相关联,会自动创建相应的代理
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
一行代码即可,感觉是有点方便,运行结果不变
- 拦截器的序列会影响结果,我们需要自己调整顺序如果是使用BeanNameAutoProxyCreator
AOP+AspectJ 面向切面编程
AspectJ常见的注解
@Before – 方法执行前运行
@After – 运行在方法返回结果后
@AfterReturning – 运行在方法返回一个结果后,在拦截器返回结果。
@AfterThrowing – 运行方法在抛出异常后,
@Around – 围绕方法执行运行,结合以上这三个通知。
创建一个Dao
package com.demo.Dao;
public interface CustomerBo {
void addCustomer();
String addCustomerReturnValue();
void addCustomerThrowException() throws Exception;
void addCustomerAround(String name);
}
实现类CustomerBoImpl
package com.demo.Dao.Impl;
import com.demo.Dao.CustomerBo;
public class CustomerBoImpl implements CustomerBo {
@Override
public void addCustomer() {
System.out.println("addCustomer() is running");
}
@Override
public String addCustomerReturnValue() {
System.out.println("addCustomerReturnValue() is running");
return "abc";
}
@Override
public void addCustomerThrowException() throws Exception {
System.out.println("addCustomerThrowException() is running");
throw new Exception("Generic Error");
}
@Override
public void addCustomerAround(String name) {
System.out.println("addCustomerAround(String name) is running, args: " + name);
}
}
然后定义一个AspectJ用来输出日志信息
package com.demo.AspectJ;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class LoggingAspect {
@Before("execution(* com.demo.Dao.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running");
System.out.println("Method " + joinPoint.getSignature().getName());
System.out.println("**********");
}
}
在applicationContext.xml中声明Beans
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd ">
<aop:aspectj-autoproxy/>
<bean id="customerBo" class="com.demo.Dao.Impl.CustomerBoImpl"/>
<bean id="logAspect" class="com.demo.AspectJ.LoggingAspect"/>
</beans>
这里用到了<aop:aspectj-autoproxy/>
开启切片自动拦截
然后在xml中注册了这个日志拦截切片
运行结果如下:
下面把其余的几个注解一起使用
package com.demo.AspectJ;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.Arrays;
@Aspect
public class LoggingAspect {
@Before("execution(* com.demo.Dao.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("logBefore() is running");
System.out.println("Method " + joinPoint.getSignature().getName());
System.out.println("**********");
}
@After("execution(* com.demo.Dao.CustomerBo.addCustomer(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("logAfter() is running");
System.out.println("Method " + joinPoint.getSignature().getName());
System.out.println("**********");
}
@AfterReturning("execution(* com.demo.Dao.CustomerBo.addCustomerReturnValue(..))")
public void logAfterReturn(JoinPoint joinPoint) {
System.out.println("logAfterReturn() is running");
System.out.println("Method " + joinPoint.getSignature().getName());
System.out.println("**********");
}
@AfterThrowing(pointcut = "execution(* com.demo.Dao.CustomerBo.addCustomerThrowException(..))", throwing = "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
System.out.println("logAfterThrowing() is running");
System.out.println("Method : " + joinPoint.getSignature().getName());
System.out.println("Error : " + error);
System.out.println("**********");
}
@Around("execution(* com.demo.Dao.CustomerBo.addCustomerAround(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("logAround() is running");
System.out.println("Method : " + joinPoint.getSignature().getName());
System.out.println("Method Parameters : " + Arrays.toString(joinPoint.getArgs()));
System.out.println("Around Before is running");
joinPoint.proceed();
System.out.println("Around After is running");
System.out.println("**********");
}
}
感觉跟写Advice差不多
流程就是这样: DaoImpl->AspectJ->xml开启aspect自动代理->xml注入->调用
- 注解可以用xml代替
<aop:before> = @Before
<aop:after> = @After
<aop:after-returning> = @AfterReturning
<aop:after-throwing> = @AfterThrowing
<aop:after-around> = @Around
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd ">
<aop:aspectj-autoproxy/>
<bean id="customerBo" class="com.demo.Dao.Impl.CustomerBoImpl"/>
<bean id="logAspect" class="com.demo.AspectJ.LoggingAspect"/>
<aop:config>
<aop:aspect id="aspectLogging" ref="logAspect">
<aop:pointcut id="pointCutBefore" expression="execution(* com.demo.Dao.CustomerBo.addCustomer(..))"/>
<aop:before method="logBefore" pointcut-ref="pointCutBefore"/>
<aop:pointcut id="pointCutAfter" expression="execution(* com.demo.Dao.CustomerBo.addCustomer(..))"/>
<aop:after method="logAfter" pointcut-ref="pointCutAfter"/>
</aop:aspect>
</aop:config>
</beans>
在xml中注册<aop:config>
在内层用<aop:aspect>
包裹,内部每声明一个pointcut就有一个响应的<aop:xxx>
与之对应,我理解为一个切片,一个执行
坚持原创技术分享,您的支持将鼓励我继续创作!