Spring——AOP编程和整合Mybatis

一,代理模式

在实际开发中,客户的需求可能会随着软件的开发而发生变化。如果在项目前期的时候,业务需求的变化对项目的影响可能不是很大。但是如果到了项目后期阶段,这时候软件的功能已经基本完成。那么如果客户这时候提出修改需求,这样可能会导致项目的影响是很大的,严重的焕可能会导致项目推动重来。

使用代理技术可以解决由于需求变化对业务代码的影响。Java代理技术的优势是实现无嵌入式的代码扩展,使得用户可以在不修改原有代码的基础上额外增加新的功能。

1.1 静态代理

静态代理是通过创建一个代理类,对已有类的方法进行功能的扩展。

  • 静态代理的优点:

1)代码直观,易于阅读;

2)代理类在程序编译之前就已经创建出来,执行效率高;

  • 静态代理的缺点:

1)当存在多个目标需要代理的时候,必须要为每个目标类创建代理类,比较繁琐;

2)每个代理类中可能会存在相同的代码,程序的维护性较差;

3)由于代理类在程序编译前就定义好了,灵活性较差

例如:银行和催收公司:

package com.chinasofti.demo01静态代理;

interface Agent {
	
	// 讨债
	void taozhai();
	
}

class IcbcBank implements Agent {

	@Override
	public void taozhai() {
		System.out.println("把钱打入工商银行账号...");
		System.out.println("还清...");
	}
	
}

class ChinaBank implements Agent {

	@Override
	public void taozhai() {
		System.out.println("把钱打入中国银行账号...");
		System.out.println("还清...");
	}
	
}

// 催收公司(代理)
class DebtAgent implements Agent {
	int num = 0;
	
	public DebtAgent(int num) {
		this.num = num;
	}
	
	@Override
	public void taozhai() {
		System.out.println("打电话问候...");
		System.out.println("上门问候...");
		System.out.println("淋红油...");
		
		if (num == 1) {
			IcbcBank bank = new IcbcBank();
			bank.taozhai();
		} else if (num == 2) {
			ChinaBank cb = new ChinaBank();
			cb.taozhai();
		}
	}
	
}


public class Demo01 {

	public static void main(String[] args) {
		DebtAgent agent = new DebtAgent(2);
		agent.taozhai();
	}

}

1.2 动态代理

与静态代理不同,动态代理的特点:

  • 静态代理是在编译之前就加入,而动态代理是在程序运行的时候才加入的;
  • 静态代理会生成代理类的class文件,而动态代理不会生成class文件;
  • 动态代理比静态代理的灵活性更好

jdk提供了java.lang.reflect.Proxy类,该类提供了创建动态代理对象的方法。

package com.chinasofti.demo02动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


interface Agent {
	
	// 讨债
	void taozhai();
	
}

class IcbcBank implements Agent {

	@Override
	public void taozhai() {
		System.out.println("把钱打入工商银行账号...");
		System.out.println("还清...");
	}
	
}

class ChinaBank implements Agent {

	@Override
	public void taozhai() {
		System.out.println("把钱打入中国银行账号...");
		System.out.println("还清...");
	}
	
}

public class Demo02 {

	public static void main(String[] args) {
		// 被代理的目标对象
		ChinaBank bank = new ChinaBank();
		// 创建代理对象
		Agent bankProxy = (Agent) Proxy.newProxyInstance(
				bank.getClass().getClassLoader(), // 与目标对象的ClassLoader相同
				bank.getClass().getInterfaces(),  // 与目标对象实现的接口相同,用来指定代理对象实现的接口
				new InvocationHandler() {

					/* 
					 * 执行被代理对象的任何方法,都会经过该方法。(non-Javadoc)
					 * 	proxy:动态代理对象的引用
					 *  method:要执行的方法
					 *  args:要执行方法的参数
					 */
					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						System.out.println("打电话问候...");
						System.out.println("上门问候...");
						System.out.println("淋红油...");
						
						// 执行目标对象的方法
						method.invoke(bank, args);
						
						return null;
					}
					
				});
		
		
		bankProxy.taozhai();
		
	}
	
}

二,AOP

2.1 AOP概述

AOP(Aspect Oriented Programming):面向切面编程。他把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。

AOP的相关术语:

名称功能
连接点(Joint Point)连接点是指那些被拦截的方法
切入点(Pointcut)切入点是指对Jointpoint进行拦截的定义
通知(Advice)通知是指拦截到Joinpoint之后所要做的事情
目标对象(Target)被代理的对象
代理(Proxy)增强后的对象
切面(Aspect)切入点和通知的结合

2.2 Spring整合AOP

第一步:导入AOP相关的jar包:

aopalliance-1.0.jar
aspectjweaver-1.9.4.jar
spring-aop-5.1.9.RELEASE.jar
spring-aspects-5.1.9.RELEASE.jar

第二步:开启AOP的支持:

<aop:aspectj-autoproxy/>

第三步:定义切面类:

@Component
@Aspect
public class Logger {

}

第四步:定义通知:

@Before("execution(* com.xjy.service.impl.*.*(..))")
public void before() {
    System.out.println("前置通知...");
}

第五步:测试:

@Test
public void testFindAll() {
	ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:beans.xml");
	ICustomerService customerService = (ICustomerService) ac.getBean("customerServiceImpl");
	customerService.findAllCustomer();
}

2.3 AOP相关注解

  • @Aspect:把当前类声明为切面
  • @Before(value=“切入表达式”):把当前方法设置为前置通知
  • @AfterReturning(value=“切入表达式”):把当前方法设置为后置通知
  • @After(value=“切入表达式”):把当前方法设置为异常通知
  • @AfterThrowing(value=“切入表达式”):把当前方法设置为异常通知
  • @Around:把当前方法设置为环绕通知,即@Before和@After的结合
  • @Pointcut(value=“切入表达式”):指定切入表达式

@AfterReturning和@After的区别?

1)它们都是在切入方法执行完后执行,但是@AfterReturning在@After之后执行;

2)如果方法出现异常,那么@AfterReturning将不会执行;而@After无论方法是否正常结束,它都会被执行;

3)@AfterReturning可以访问目标方法的返回值,而@After就无法做到

@AfterReturning(value="execution(* com.xjy.service.impl.*.*(..))", returning="rt")
public void afterReturn(Object rt) throws Throwable {
	System.out.println("切入方法的返回值:" + rt);
	System.out.println("方法返回通知...");
}

注意:returning属性值要与增强方法的参数名相同。

三,AOP零配置

首先创建一个配置类,使用@EnableAspectJAutoProxy注解启用AOP功能。

@Configuration
@ComponentScan(basePackages={"com.chinasofti"})
// 启用aop功能
@EnableAspectJAutoProxy
class SpringConfig {

	
}

然后在main方法中使用AnnotationConfigApplicationContext创建Spring容器。

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);

四,Spring整合Mybatis

4.1 整合步骤

第一步:导入jar包

mybatis-spring-1.3.2.jar

第二步:在映射接口上使用@Repository注解

@Repository
public interface UserMapper {

	void addUser(User user);
	
}

第三步:把Mapper接口注入到业务层

public class UserServiceImpl implements IUserService {
	@Autowired
	private UserMapper userMapper;

}

第四步:编写测试类

package springqs.test;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import springqs.beans.User;
import springqs.service.IUserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={UserServiceTest.class})
@Configuration
@ComponentScan(basePackages={"com.lmc"})
@MapperScan("com.lmc.mapper")
public class UserServiceTest {
	@Autowired
	private IUserService userService;
	
	@Bean(name="dataSource")
	public DataSource getDataSource() {
		DriverManagerDataSource ds = new DriverManagerDataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost:3306/test");
		ds.setUsername("root");
		ds.setPassword("root");
		return ds;
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource")DataSource ds) throws Exception {
		SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
		sessionFactory.setDataSource(ds);
		return sessionFactory.getObject();
	}
	
	@Test
	public void testAddUser() {
		User user = new User();
		user.setName("ddee");
		user.setAge(12);
		userService.addUser(user);
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值