什么是AOP?
AOP底层原理:AOP就是代理机制,动态代理:(JDK 中使用) JDK动态代理,对实现了接口的类生成代理。
package spring3.aop.demo1;
/**
* DAO的接口
*
*/
public interface UserDao {
public void add();
public void update();
}
UserDaoImpl
package spring3.aop.demo1;
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("添加用户");
}
@Override
public void update() {
System.out.println("修改用户");
}
}
JDKProxy
package spring3.aop.demo1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK的动态代理机制
*
* @author liuxun
*
*/
public class JDKProxy implements InvocationHandler {
private UserDao userDao;
public JDKProxy(UserDao userDao) {
super();
this.userDao = userDao;
}
public UserDao createProxy() {
UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(), this);
return proxy;
}
@Override
// 调用目标对象的任何一个方法都相当于invoke()
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("add".equals(method.getName())) {
// 记录日志
System.out.println("日志记录===================");
Object result = method.invoke(userDao, args);
return result;
}
return method.invoke(userDao, args);
}
}
SpringTest1
package spring3.aop.demo1;
import org.junit.Test;
public class SpringTest1 {
@Test
public void demo1() {
UserDao userDao = new UserDaoImpl();
userDao.add();
userDao.update();
}
@Test
public void demo2() {
// 被代理对象
UserDao userDao = new UserDaoImpl();
// 创建代理对象的时候传入被代理对象
UserDao proxy = new JDKProxy(userDao).createProxy();
proxy.add();
proxy.update();
}
}
运行结果如下:
package spring3.aop.demo2;
public class ProductDao {
public void add() {
System.out.println("添加商品...");
}
public void update() {
System.out.println("修改商品...");
}
}
CGLibProxy
package spring3.aop.demo2;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/**
* 使用CGLib生成代理对象
*
*/
public class CGLibProxy implements MethodInterceptor {
private ProductDao productDao;
public CGLibProxy(ProductDao productDao) {
super();
this.productDao = productDao;
}
public ProductDao createProxy() {
// 使用CGLIB生成代理
// 1.创建核心类
Enhancer enhancer = new Enhancer();
// 2.为其设置父类
enhancer.setSuperclass(productDao.getClass());
// 3.设置回调
enhancer.setCallback(this);
// 4.创建代理
return (ProductDao) enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("add".equals(method.getName())) {
System.out.println("日志记录=================");
// Object obj=method.invoke(productDao, args);
Object obj = methodProxy.invokeSuper(proxy, args);// 代理方法中执行代理对象父类中的方法
return obj;
}
return methodProxy.invokeSuper(proxy, args);
}
}
SpringTest2
package spring3.aop.demo2;
import org.junit.Test;
public class SpringTest2 {
@Test
public void demo1() {
ProductDao productDao = new ProductDao();
productDao.add();
productDao.update();
}
@Test
public void demo2() {
ProductDao productDao = new ProductDao();
ProductDao proxy=new CGLibProxy(productDao).createProxy();
proxy.add();
proxy.update();
}
}
运行结果如下所示
/**
*@param obj CGlib根据指定父类生成的代理对象
*@param method 拦截的方法
*@param args 拦截方法的参数数组
*@param proxy 方法的代理对象,用于执行父类的方法
*@return
*/
public Object intercept(Object obj, Methodmethod, Object[] args,
MethodProxyproxy) throws Throwable {
... ...
}
spring生成代理基于ProxyFactoryBean类,底层自动选择使用JDK的动态代理还是CGLIB的代理。
package spring3.aop.demo3;
public interface CustomerDao {
public void add();
public void update();
public void delete();
public void find();
}
真实实现类CustomerDaoImpl
package spring3.aop.demo3;
public class CustomerDaoImpl implements CustomerDao {
public void add() {
System.out.println("添加客户");
}
public void update() {
System.out.println("修改客户");
}
public void delete() {
System.out.println("删除客户");
}
public void find() {
System.out.println("查询客户");
}
}
定义增强类型MyBeforeAdvice
package spring3.aop.demo3;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
/**
* 前置增强
*/
public class MyBeforeAdvice implements MethodBeforeAdvice {
/**
* method:执行的方法
* args:参数
* target:目标对象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置增强...");
}
}
配置增强applicationContext.xml
新建测试类SpringTest3
package spring3.aop.demo3;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest3 {
@Autowired
// @Qualifier("customerDao") // 需要注入真实的对象,必须注入代理对象
@Qualifier("customerDaoProxy")
private CustomerDao customerDao;
@Test
public void demo1() {
customerDao.add();
customerDao.update();
customerDao.delete();
customerDao.find();
}
}
测试demo1 运行结果如下
package spring3.aop.demo4;
/**
* 目标对象
*
*/
public class OrderDao {
public void add() {
System.out.println("添加订单");
}
public void update() {
System.out.println("修改订单");
}
public void delete() {
System.out.println("删除订单");
}
public void find() {
System.out.println("查询订单");
}
}
MyAroundAdvice (Advice通知增强类)
package spring3.aop.demo4;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* 增强的类
* 使用的是环绕增强
* 注意:对于增强类型的接口可以使用AOP联盟的也可以使用Spring扩展后自带的
*/
public class MyAroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("环绕前增强...");
Object result=methodInvocation.proceed(); // 指定目标对象的方法
System.out.println("环绕后增强...");
return result;
}
}
applicationContext.xml (进行配置)
运行结果如下:
SpringTest5 新建测试类
package spring3.aop.demo5;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import spring3.aop.demo3.CustomerDao;
import spring3.aop.demo4.OrderDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringTest5 {
@Autowired
@Qualifier("orderDao")
private OrderDao OrderDao;
@Autowired
@Qualifier("customerDao")
private CustomerDao CustomerDao;
@Test
public void demo1() {
OrderDao.add();
OrderDao.delete();
CustomerDao.update();
}
}
运行结果如下:
SpringTest6 测试类
package spring3.aop.demo6;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import spring3.aop.demo3.CustomerDao;
import spring3.aop.demo4.OrderDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class SpringTest6 {
@Autowired
@Qualifier("orderDao")
private OrderDao orderDao;
@Autowired
@Qualifier("customerDao")
private CustomerDao customerDao;
@Test
public void demo1() {
orderDao.add();
orderDao.update();
orderDao.delete();
customerDao.add();
}
}
运行结果如下:
AspectJ表达式
package aop.aspectj.demo1;
public class UserDao {
public void add(){
System.out.println("添加用户");
}
public int update(){
System.out.println("修改用户");
return 1;
}
public void delete(){
System.out.println("删除用户");
int d = 1/ 0;
}
public void find(){
System.out.println("查询用户");
}
}
MyAspect 注解实现AspectJ的切面
package aop.aspectj.demo1;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
*
* 切面类:就是切点和增强的组合
*
*/
@Aspect
public class MyAspect {
@Before("execution(* aop.aspectj.demo1.UserDao.add(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置增强..." + joinPoint);
}
@AfterReturning(value = "execution(* aop.aspectj.demo1.UserDao.update(..))", returning = "returnVal")
public void afterReturning(Object returnVal) {
System.out.println("后置增强...方法的返回值" + returnVal);
}
@AfterThrowing(value = "MyAspect.myPointcut1()", throwing = "e")
public void afterThrowing(Throwable e) {
System.out.println("警告:出现异常了!!! " + e.getMessage());
}
@After("MyAspect.myPointcut1()||MyAspect.myPointcut2()")
public void after(){
System.out.println("最终通知...");
}
@Pointcut("execution(* aop.aspectj.demo1.UserDao.delete(..))")
public void myPointcut1() {
}
@Pointcut("execution(* aop.aspectj.demo1.UserDao.find(..))")
public void myPointcut2() {
}
}
编写测试类 SpringTest1
package aop.aspectj.demo1;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest1 {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Test
public void demo1() {
userDao.add();
userDao.update();
userDao.find();
userDao.delete();
}
}
运行结果如下:
package aop.aspectj.demo2;
public class ProductDao {
public int add() {
System.out.println("添加商品...");
int d = 10 / 0;
return 100;
}
public void update() {
System.out.println("修改商品...");
}
public void delete() {
System.out.println("删除商品...");
}
public void find() {
System.out.println("查询商品...");
}
}
MyAspectXML 切面类
package aop.aspectj.demo2;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 切面类
*/
public class MyAspectXML {
public void before() {
System.out.println("前置通知...");
}
public void afterReturning(Object returnVal) {
System.out.println("后置通知...返回值:" + returnVal);
}
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前增强...");
Object result = proceedingJoinPoint.proceed();
System.out.println("环绕后增强...");
return result;
}
public void afterThrowing(Throwable e) {
System.out.println("异常通知..." + e.getMessage());
}
public void after() {
System.out.println("最终通知...");
}
}
applicationContext2.xml 配置切面类
SpringTest2 测试类
package aop.aspectj.demo2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class SpringTest2 {
@Autowired
@Qualifier("productDao")
private ProductDao productDao;
@Test
public void demo1() {
productDao.update();
productDao.delete();
productDao.find();
productDao.add();
}
}
运行结果如下
// JDBC模板 依赖连接池获得数据库连接,所有必须先构造连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring");
dataSource.setUsername("root");
dataSource.setPassword("123");
// 创建JDBC模板
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
// 建表SQL语句
String sql = "create table customers(id int primary key auto_increment,name varchar(20))";
jdbcTemplate.execute(sql);
==================================================
可以写为
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c\:mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=info, stdout
applicationContext.xml
SpringTest1
package spring3.jdbctemplate.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest1 {
@Autowired
@Qualifier("jdbcTemplate")
JdbcTemplate jdbcTemplate;
@Test
// 手动配置Spring自带的数据源
public void demo1() {
// 创建连接
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// 设置参数
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring3_day02");
dataSource.setUsername("root");
dataSource.setPassword("root");
// 使用JDBC模板
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute("create table user (id int primary key auto_increment,name varchar(20))");
}
@Test
public void demo2() {
jdbcTemplate.execute("insert into user values(null,'spring_dataSource')");
}
}
运行demo1
package spring3.jdbctemplate.demo2;
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
UserDao
package spring3.jdbctemplate.demo2;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class UserDao extends JdbcDaoSupport {
public void add(User user) {
String sql = "insert into user values(null,?)";
this.getJdbcTemplate().update(sql, user.getName());
}
public void update(User user) {
String sql = "update user set name= ? where id= ?";
this.getJdbcTemplate().update(sql);
}
public void delete(User user) {
String sql = "delete from user where id= ?";
this.getJdbcTemplate().update(sql, user.getId());
}
public int findCount() {
String sql = "select count(*) from user";
return this.getJdbcTemplate().queryForInt(sql);
}
public String findNameById(int id) {
String sql = "select name from user where id = ?";
return this.getJdbcTemplate().queryForObject(sql, String.class, id);
}
public User findById(int id) {
String sql = "select * from user where id = ?";
return this.getJdbcTemplate().queryForObject(sql, new UserRowMapper(), id);
}
public List findAll() {
String sql = "select * from user";
return this.getJdbcTemplate().query(sql, new UserRowMapper());
}
class UserRowMapper implements RowMapper {
/**
* rs: 结果集 rowNum: 行号
*/
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
return user;
}
}
}
在applicationContext.xml文件中添加如下配置
测试SpringTest2
package spring3.jdbctemplate.demo2;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest2 {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Test
public void demo1() {
User user = new User();
user.setName("小胖");
userDao.add(user);
}
@Test
public void demo2() {
User user = new User();
user.setId(1);
user.setName("小边");
userDao.update(user);
}
@Test
public void demo3() {
User user = new User();
user.setId(1);
userDao.delete(user);
}
@Test
public void demo4() {
int count = userDao.findCount();
System.out.println(count);
}
@Test
public void demo5() {
String name = userDao.findNameById(3);
System.out.println(name);
}
@Test
public void demo6() {
User user = userDao.findById(3);
System.out.println(user);
}
@Test
public void demo7() {
List list = userDao.findAll();
for (User user : list) {
System.out.println(user);
}
}
}
由代码和测试可以发现 JDBCTemplate和DBUtils很类似