目录
一、引言
初次碰到是因为日志管理问题,想为每个请求的一些操作都创建日志记录,添加代码添加的蛋疼,所以有了今天的主角AOP,面向切面,其实就是不改变原代码进行一些操作。
AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
二、简单原理
不改变原代码进行一些操作有木有很熟悉,AOP的本质就是代理模式,代理类为我们在操作目标类的前后添加了一些自定义操作。这里代理分为静态代理和动态代理,动态代理分为jdk实现和cglib实现。
只需要记住静态代理是在编译的时候生成代理类(就理解为手动写一个代理类,在目标类函数调用前后写一些硬编码的操作);而动态代理是在运行时生成代理类,这个代理类本质通过反射生成(目标类有接口使用jdk实现,没有接口使用cglib实现),spring只是把动态代理两种方式封装了。
三、代码实现
1、xml配置
目标类,要在该类的方法前后添加操作
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public Object getUser(String name)
{
return userMapper.selectUser1(name);
}
}
增强类,要在目标类的前后进行这种操作
public class MyLogg {
public void prelog()
{
System.out.println("----------------------beforeservice--------------------------");
}
public void afterlog()
{
System.out.println("------------------------afterservice-------------------------");
}
}
配置xml文件,将目标类与增强类通过配置连接起来,扫描目标类的包,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.xcy.service"></context:component-scan>
<bean id="mylog" class="com.xcy.aspect.MyLogg"></bean>
<aop:config>
<aop:pointcut expression="execution(public * com.xcy.service.*.*(..))"
id="servicePointcut"/>
<aop:aspect id="logAspect" ref="mylog">
<aop:before method="prelog" pointcut-ref="servicePointcut" />
<aop:after-returning method="afterlog" pointcut-ref="servicePointcut" />
</aop:aspect>
</aop:config>
</beans>
2、注解
目标类,要在该类的方法前后添加操作
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public Object getUser(String name)
{
return userMapper.selectUser1(name);
}
}
增强类,要在目标类的前后进行这种操作
@Component
@Aspect
public class MyLogg {
@Pointcut("execution(* com.xcy.service.*.*(..))")//切入点
public void testPointCut(){
}
@Before("testPointCut()")
public void prelog()
{
System.out.println("----------------------beforeservice--------------------------");
}
@After("testPointCut()")
public void afterlog()
{
System.out.println("------------------------afterservice-------------------------");
}
@Around("testPointCut()")
public Object aroundlog(ProceedingJoinPoint pjp)
{
Object returnValue=null;
System.out.println("----------------------Before--------------------------");
try {
returnValue= pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("------------------------AfterThrowing-------------------------");
}
finally {
System.out.println("------------------------After-------------------------");
}
System.out.println("------------------------AfterReturning-------------------------");
return returnValue;
}
}
xml配置,扫描目标类包,扫描增强类包,开启aop
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.xcy.service"></context:component-scan>
<context:component-scan base-package="com.xcy.aspect"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>
四、总结
- AOP使用场景;
- AOP简单原理;
- AOP代码实现;