创建一个A对象,一个B对象,和一个后处理器(beanPostProcessor),在后处理器中创建一个A对象的代理对象(Proxy)
public interface UserService {
void show1();
void show2();
}
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void show1() {
System.out.println("show1....");
}
public void show1(String aaa) {
System.out.println("show1....");
}
@Override
public void show2() {
System.out.println("show2....");
//int i = 1/0;
}
public void show3() {
System.out.println("show3....");
}
}
public class MyAdvice {
public void beforeAdvice(JoinPoint joinPoint){
System.out.println("前置的增强....");
}
public void afterReturningAdvice(){
System.out.println("后置的增强....");
}
}
public class MockAopBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//目的:对UserServiceImpl中的show1和show2方法进行增强,增强方法存在与MyAdvice中
//问题1:筛选service.impl包下的所有的类的所有方法都可以进行增强,解决方案:if-else
//问题2:MyAdvice怎么获取到?解决方案:从Spring容器中获得MyAdvice
//只对指定包下的方法进行增强
if(bean.getClass().getPackage().getName().equals("com.itheima.service.impl")){
//生成当前Bean的Proxy对象
Object beanProxy = Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
(Object proxy, Method method, Object[] args) -> {
MyAdvice myAdvice = applicationContext.getBean(MyAdvice.class);
//执行增强对象的before方法
myAdvice.beforeAdvice();
//执行目标对象的目标方法
Object result = method.invoke(bean, args);
//执行增强对象的after方法
myAdvice.afterAdvice();
return result;
}
);
//返回代理对象
return beanProxy;
}
//表示该类不需要进行增强,则直接返回
return bean;
}
//注入
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
org.aspectj
aspectjweaver
1.9.6
切点表达式的配置方式有两种,直接将切点表达式配置在通知上,也可以将切点表达式抽取到外面,在通知上 进行引用
通知类实现了前置通知和后置通知接口
public class MyAdvice2 implements MethodBeforeAdvice, AfterReturningAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("前置通知..........");
}
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("后置通知...........");
}
}
通知类实现了方法拦截器接口
public class MyAdvice3 implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("环绕前******");
//执行目标方法
Object res = methodInvocation.getMethod().invoke(methodInvocation.getThis(), methodInvocation.getArguments());
System.out.println("环绕后******");
return res;
}
}
硬核讲解
90-Spring的AOP开发-AOP底层两种生成Proxy方式_哔哩哔哩_bilibili
//切点表达式的抽取
@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
public void myPointcut(){}
@Around("MyAdvice.myPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前的增强....");
Object res = proceedingJoinPoint.proceed();//执行目标方法
System.out.println("环绕后的增强....");
return res;
}
//增强类,内部提供增强方法
@Component
@Aspect
public class MyAdvice {
//切点表达式的抽取
@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
public void myPointcut(){}
//
@Before("execution(* com.itheima.service.impl.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint){
//System.out.println("当前目标对象是:"+joinPoint.getTarget());
//System.out.println("表达式:"+joinPoint.getStaticPart());
System.out.println("前置的增强....");
}
@AfterReturning("execution(* com.itheima.service.impl.*.*(..))")
public void afterReturningAdvice(){
System.out.println("后置的增强....");
}
@Around("MyAdvice.myPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前的增强....");
Object res = proceedingJoinPoint.proceed();//执行目标方法
System.out.println("环绕后的增强....");
return res;
}
@AfterThrowing(pointcut = "execution(* com.itheima.service.impl.*.*(..))",throwing = "e")
public void afterThrowingAdvice(Throwable e){
System.out.println("当前异常信息是:"+e);
System.out.println("异常抛出通知...报异常才执行");
}
@After("execution(* com.itheima.service.impl.*.*(..))")
public void afterAdvice(){
System.out.println("最终的增强....");
}
}
@Component
@Aspect
public class MyAdvice {
//切点表达式的抽取
@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
public void myPointcut(){}
//
@Before("execution(* com.itheima.service.impl.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint){
//System.out.println("当前目标对象是:"+joinPoint.getTarget());
//System.out.println("表达式:"+joinPoint.getStaticPart());
System.out.println("前置的增强....");
}
@AfterReturning("execution(* com.itheima.service.impl.*.*(..))")
public void afterReturningAdvice(){
System.out.println("后置的增强....");
}
@Around("MyAdvice.myPointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前的增强....");
Object res = proceedingJoinPoint.proceed();//执行目标方法
System.out.println("环绕后的增强....");
return res;
}
@AfterThrowing(pointcut = "execution(* com.itheima.service.impl.*.*(..))",throwing = "e")
public void afterThrowingAdvice(Throwable e){
System.out.println("当前异常信息是:"+e);
System.out.println("异常抛出通知...报异常才执行");
}
@After("execution(* com.itheima.service.impl.*.*(..))")
public void afterAdvice(){
System.out.println("最终的增强....");
}
}
config/SpringCofig
@Configuration
@ComponentScan("com.itheima") //
@EnableAspectJAutoProxy //aop自动代理---->
public class SpringConfig {
}
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService bean = app.getBean(UserService.class);
bean.show2();
public interface AccountMapper {
//使用注解方式写
//+钱
@Update("update tb_account set money=money+#{money} where account_name=#{accountName}")
//Param:要进行映射
public void incrMoney(@Param("accountName") String accountName,@Param("money") Integer money);
//-钱
@Update("update tb_account set money=money-#{money} where account_name=#{accountName}")
public void decrMoney(@Param("accountName") String accountName,@Param("money") Integer money);
}
public interface AccountService {
//转钱
void transferMoney(String outAccount,String inAccount,Integer money);
}
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired//注入
private AccountMapper accountMapper;
public void transferMoney(String outAccount, String inAccount, Integer money) {
accountMapper.decrMoney(outAccount,money);
int i = 1/0;//错误代码
accountMapper.incrMoney(inAccount,money);
}
public void registAccount(){
}
}
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
硬核讲解:
98-Spring的事务控制-xml方式声明式事务控制原理剖析_哔哩哔哩_bilibili
@Configuration
@ComponentScan("com.itheima")//组件扫描
@PropertySource("classpath:jdbc.properties")//加载jdbc配置文件
@MapperScan("com.itheima.mapper")//mapper扫描
//事务的自动代理(注解驱动)
@EnableTransactionManagement //
public class SpringConfig {
//配置数据源信息
@Bean("dataSource")
public DataSource dataSource(
@Value("${jdbc.driver}") String driver,
@Value("${jdbc.url}") String url,
@Value("${jdbc.username}") String username,
@Value("${jdbc.password}") String password
) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
//配置SqlSessionFactoryBean,作用将SqlSessionFactory存储到spring容器
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
//MapperScannerConfigurer,作用扫描指定的包,产生Mapper对象存储到Spring容器
@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
}