【=====AOP即 Aspect Oriented Program 面向切面编程(公共功能集中解决),目的是为了让我们专心的做业务 。不改变源码的基础上新增功能,是Spring最为重要的功能之一 =====】

AOP相关术语:
- 增强处理(Advice)----五种增强方式
- 切入点(Pointcut):在哪些类,哪些方法上切入(where)
- 连接点(Join Point):连接点=通知,在方法执行的什么实际(when:方法前/方法后/方法前后)做什么(what:增强的功能)
- 切面(Aspect):切面 = 切入点 + 通知,通俗点就是:在什么时机,什么地方,做什么增强。
- 目标对象(Target object):业务
- AOP代理(AOP proxy):代理类,xml文件
- 织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成)
| 目录 | 说明 | 使用 |
|---|---|---|
| 前置增强 | 在目标方法前织入增强处理 | before |
| 后置增强 | 在目标方法之后正常执行,执行通知,若是报错,不执行 | after-returning |
| 最终增强 | 在目标方法执行之后,只有在方法成功完成时,才能执行通知。 | after |
| 异常增强 | 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知 | after-throwing |
| 环绕增强 | 在一个方法执行之前,执行通知 | around |
【当目标方法出错时,后置增强不执行,最终增强会执行;有异常执行异常增强,不报错执行后置增强】
【五种增强的整个demo代码下面已给,需要自取,接口和方法随意建吧】
//pom.xml
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.5version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
//dao、service接口
public interface UserDao {
public int addNewUser(User user);
}
//dao实现
public class UserDaoImpl implements UserDao {
public int addNewUser(User user) {
System.out.println("新添加一个对象~~~");
return 0;
}
}
//service实现
@Setter
public class UserServiceImpl implements UserService {
private UserDao userDao;
public int addNewUser(User user) {
return userDao.addNewUser(user);
}
}
/**
* 增强类
*/
public class UserLogger {
private static final Logger log = Logger.getLogger(UserServiceLogger.class);
//前置增强
public void beforeLogger(JoinPoint jp) {
System.out.print("我是前置增强…………");
System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
//后置增强
public void afterReturning(JoinPoint jp, Object result) {
System.out.print("我是后置增强…………");
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
//最终增强
public void afterLogger(JoinPoint jp) {
System.out.print("我是最终增强…………");
log.info("最终增强:"+jp.getSignature().getName()+"方法结束执行。");
}
//异常增强
public void afterThrowing(JoinPoint jp,RuntimeException e){
log.error("异常抛出:"+jp.getSignature().getName()+"方法发生异常:"+e);
}
//环绕增强,需要调用目标方法
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{
System.out.println("环绕增强开始…………");
log.info("环绕增强:调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法,方法入参:"+Arrays.toString(jp.getArgs()));
try{
Object result = jp.proceed(); //调用目标方法
log.info("环绕增强:调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法。方法返回值:"+result);
return result;
}catch(Throwable e){
log.error("环绕增强:"+jp.getSignature().getName()+"方法发生异常:"+e);
throw e;
}finally{
log.info("环绕增强:"+jp.getSignature().getName()+"方法结束执行。");
System.out.println("环绕增强结束~~~");
}
}
}
//添加关于aop的头部文件:
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
<bean id="serviceLogger" class="com.jules.aop.UserLogger"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.jules.service.*.*.*(..))">aop:pointcut>
<aop:aspect ref="serviceLogger">
<aop:before method="beforeLogger" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
<aop:after method="afterLogger" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
<aop:around method="aroundLogger" pointcut-ref="pointcut"/>
aop:aspect>
aop:config>
public class Test {
@Test
public void addNewUser() {
//使用ClassPathXmlApplicationContext读取配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("配置文件名");
//使用getBean("bean中ID属性值")获取对象
UserService userService = (UserService) context.getBean("userService");
userService.addNewUser(new User()); //添加空对象测试异常增强
}
}
| 目录 | 说明 |
|---|---|
| aop:config | AOP配置 |
| aop:pointcut | 定义切点 |
| aop:aspect | 定义切面 |
| aop:before | 定义前置增强 |
| aop:after-returning | 定义后置增强 |
| aop:after | 定义最终增强 |
| aop:after-throwing | 定义异常增强 |
| aop:around | 定义环绕增强 |
| aop:aspectj-autoproxy/ | 启动@AspectJ注解驱动的切面 |
<aop:pointcut id="pointcut" expression="execution(* com.jules.service.*.*.*(..))">aop:pointcut>
public * addNewUser(entity.User)----- “ * ”表示匹配所有类型的返回值。
public void *(entity.User)------“ * ”表示匹配所有方法名。
public void addNewUser(..)-------“..”表示匹配所有参数个数和类型。
* com.service.*.*(..)-------匹配com.service包下所有类的所有方法。
* com.service..*.*(..)-------匹配com.service包及其子包下所有类的所有方法
使用注解开发,则配置文件中创建的bean就可以被代替掉
<bean id="userDao" class="com.hz.dao.impl.UserDaoImpl">bean>
<bean id="userService" class="com.hz.service.impl.UserServiceImpl"/>
【其他类用@Component,虽然哪里都可以使用但为了辨识,出现了下面的注解
Dao实现用@Repository,service用@Service,控制类用@Controller】
( 在dao类和service类也可以使用的,但一般用来标注其他类,用于明显区别 )第一步:使用注解前要先开启注解:添加context的命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
ttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">
第二步:添加扫描,标注要是用注解的类
<context:component-scan base-package="com.jules,service,com,jules.dao" />
第三步:使用示例
@Component //直接使用相当于有一个别名"userDaoImpl"
@Component("userDao") //自己命名,等效
@Repository("userDao") //与@Component的使用没区别
public class UserDaoImpl implements UserDao{
}

@Resource 是java下的包,import javax.annotation.Resource;
@Autowired 实际是按数据类型进行注入的。是spring下的包,import org.springframework.beans.factory.annotation.Autowired;
它是根据UserDao 类型注入的------
倘若有private UserDao userDao11;private UserDao userDao22;它是无法识别的,要与@Qualifier("")搭配使用变为按名字进行注入。
@Autowired+@Qualifier("userDao")=====@Resource(name = "userDao")
//@Setter
@Service("userService)
public class UserServiceImpl implements UserService {
//在service层中要引用dao层,bean的关系绑定
@Resource
@Autowired
private UserDao userDao;
public int addNewUser(User user) {
user.setUserName(uname);
user.setUserCode(ucode);
return userDao.addNewUser(user);
}
}

启动@AspectJ注解的支持之前在介绍五种增强的时候,spring配置文件中的实例化增强类bean和定义切面的配置就不需要,只需要扫描包和开启AOP注解就可。
<context:component-scan base-package="com.jules.aop"/>
<aop:aspectj-autoproxy/>
**/**
* 使用注解定义切面
*/
@Component
@Aspect
public class UserServiceLogger {
private static final Logger log = Logger.getLogger(UserServiceLogger.class);
@Pointcut("execution(* com.hz.service.*.*(..))")
public void pointcut() {
}
//前置增强
@Before("pointcut()")
public void beforeLogger(JoinPoint jp) {
System.out.print("我是前置增强…………");
System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
//后置增强
@AfterReturning(pointcut = "pointcut()", returning = "result")
public void afterReturning(JoinPoint jp, Object result) {
System.out.print("我是后置增强…………");
log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
//最终增强
@After("pointcut()")
public void afterLogger(JoinPoint jp) {
System.out.println("我是最终增强…………");
log.info("最终增强:"+jp.getSignature().getName()+"方法结束执行。");
}
//异常增强
@AfterThrowing(pointcut = "pointcut()", throwing = "e")
public void afterThrowing(JoinPoint jp,RuntimeException e){
log.error("异常抛出:"+jp.getSignature().getName()+"方法发生异常:"+e);
}
//环绕增强,需要调用目标方法
@Around("pointcut()")
public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable{
System.out.println("环绕增强开始==========");
log.info("环绕增强:调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法,方法入参:"+Arrays.toString(jp.getArgs()));
try{
Object result = jp.proceed(); //调用目标方法
log.info("环绕增强:调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法。方法返回值:"+result);
return result;
}catch(Throwable e){
log.error("环绕增强:"+jp.getSignature().getName()+"方法发生异常:"+e);
throw e;
}finally{
log.info("环绕增强:"+jp.getSignature().getName()+"方法结束执行。");
System.out.println("环绕增强结束=============");
}
}
}


容器的对象的获取使用AnnotationConfigApplicationContext



依赖注入:@Autowired注入引用类型(上面讲解过),@Value注入普通类型

加载properties的配置文件:

注解开发管理第三方Bean,没有配置文件

倘若此类中还要加载其他东西,太混乱了,要把他们分开进入不同类中,在SpringConfig中加载
方式一:

方式二:不推荐,麻烦


