springday04(aop)

aop的注解方式实现
spring也支持注解方式实现aop,相对于配置文件的方式,注解配置更加的轻量级,配置修改更加的方便,是目前最流行的方式。
a.开启aop的注解配置方式

 <!--注解方式配置aop开关  -->
	 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

b.将指定的类标志为一个切面,并配置id

@Aspect
public class FirstAspect {
	@Pointcut("execution(* cn.tedu.service..*.*(..))")
	public void mx(){
		
	}

c.配置通知 指定切入点规则
前置通知 @Before
环绕通知@Around
后置通知@AfterReturning
异常通知@AftereThrowing
最终通知@After在这里插入图片描述
代码实现:

package cn.tedu.aspect;
//切面类
import java.lang.reflect.Method;
import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import cn.tedu.domain.User;

@Component
@Aspect
public class FirstAspect {
	@Pointcut("execution(* cn.tedu.service..*.*(..))")
	public void mx(){
		
	}
	/**
	 * 前置
	 * @param jp
	 */
	@Before("mx()")
	public void before(JoinPoint jp){
		System.out.println("前置通知1..");
		//获取目标对象
		Object targetObj=jp.getTarget();
		System.out.println(targetObj);
		//获取目标方法
		MethodSignature msig=(MethodSignature) jp.getSignature();
		Method m=msig.getMethod();
		System.out.println(m.getName());
		System.out.println(m.getReturnType());
		System.out.println(Arrays.asList(m.getParameterTypes()));
	}
	/**
	 * 环绕
	 * @param pjp
	 * @return
	 * @throws Throwable
	 */
	@Around("mx()")
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("环绕通知1...before..");
		//执行目标方法
		Object retuObj=pjp.proceed();
		System.out.println("环绕通知1...after..");
		return retuObj;
		//return new User(33,"zsf","sf","dsf");//慎用,这里不是service层
	}
	/**
	 * 后置
	 */
	@AfterReturning(value="mx()",returning="reObj")
	public void afterReturning(JoinPoint jp,Object reObj){
		System.out.println("后置通知1..."+reObj);
		Object obj=jp.getTarget();
		System.out.println(obj);
		MethodSignature signature=(MethodSignature) jp.getSignature();
		Method method=signature.getMethod();
		System.out.println(method.getName());
		System.out.println(method.getReturnType());
		System.out.println(Arrays.asList(method.getParameterTypes()));
	}
	/**
	 * 异常
	 */
	@AfterThrowing(value="mx()",throwing="e")
	public void afterThrowing(JoinPoint jp,Throwable e){
		System.out.println("异常通知1..."+e.getMessage());
	}
	/**
	 * 最终
	 */
	@After("mx()")
	public void after(){
		System.out.println("最终通知1...");
	}
}

案例aop:
1.异常信息收集
有异常抛出,根据异常信息记录日志
代码实现:

package cn.tedu.aspect;



import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class FirstAspect {
	@Pointcut("execution(* cn.tedu.service..*.*(..))")
	public void mx(){
		
	}
	private Logger logger=Logger.getLogger(FirstAspect.class);
	@AfterThrowing(value="mx()",throwing="e")
	public void afterThrowing(JoinPoint jp,Throwable e){
		Object obj=jp.getTarget();
		MethodSignature signature=(MethodSignature) jp.getSignature();
		logger.error("在访问["+obj+"]的["+signature.getMethod().getName()+"]方法时抛出了["+e.getMessage()+"]异常");
	}
}

package cn.tedu.service;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{
	@Override
	public void add(){
		System.out.println("增加用户");
		//int i=1/0;
	}
}

package cn.tedu.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import cn.tedu.service.UserService;
@Controller
public class UserServlet {
	@Autowired
	UserService userService=null;
	public void addUser(){
		userService.add();
	}
}

package cn.tedu.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.tedu.web.UserServlet;

public class test01 {
	@Test
	public void test01(){
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserServlet userServlet=(UserServlet) context.getBean("userServlet");
		userServlet.addUser();
	}
}

配置:

 <!-- 配置ioc -->
	 <context:component-scan base-package="cn.tedu.web"></context:component-scan>
	 <context:component-scan base-package="cn.tedu.service"></context:component-scan>
	 <context:component-scan base-package="cn.tedu.dao"></context:component-scan>
	 <context:component-scan base-package="cn.tedu.aspect"></context:component-scan>
	 <!--注解方式配置aop开关  -->
	 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

2.方法执行所用的时间

package cn.tedu.aspect;



import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class FirstAspect2 {
	@Pointcut("execution(* cn.tedu.service..*.*(..))")
	public void mx(){
		
	}
	@Around(value="mx()")
	public void around(ProceedingJoinPoint pjp) throws Throwable{
		long start=System.currentTimeMillis();
		Object obj=pjp.proceed();
		long end=System.currentTimeMillis();
		long useTime=end-start;
		System.out.println("调用["+pjp.getTarget()+"]的["+pjp.getSignature().getName()+"]所用时间为["+useTime+"]");
	}
}

package cn.tedu.service;

import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{
	@Override
	public void add(){
		System.out.println("增加用户");
		//int i=1/0;
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

3.实现事务控制(原代码在SpringDay04_03aop_demo项目中)
通过aop实现事务控制,通过注解来标识方法是否需要事务
在切面中通过判断目标方法是否具有事务注解决定是否执行事务
通过事务管理器管理事务防止耦合
代码实现

package cn.tedu.aspect;



import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import cn.tedu.anno.Trans;
import cn.tedu.util.TransactionManager;
@Component
@Aspect
public class TransAspect {
	
	
	@Around(value="execution(* cn.tedu.service..*.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		//获取目标对象
		Object target=pjp.getTarget();
		//获取当前方法(接口上的方法)----注解在实现类的方法上
		MethodSignature signature=(MethodSignature) pjp.getSignature();
		Method method=signature.getMethod();
		//在目标身上获取该方法(实现类上的方法)
		Method instance_method=target.getClass().getMethod(method.getName(), method.getParameterTypes());
		//判断当前方法上有没有@Tran修饰
		if(method.isAnnotationPresent(Trans.class)||instance_method.isAnnotationPresent(Trans.class)){
			try {
				TransactionManager.startTran();
				Object reObj=pjp.proceed();
				TransactionManager.commitTran();
				return reObj;
			} catch (Exception e) {
				TransactionManager.rollbacktTran();
				throw e;
			}finally{
				TransactionManager.release();
			}
		}else{//没有注解说明不需要事务,不管理事务
			try{
				Object reObj=pjp.proceed();
				return reObj;
			}finally{
				TransactionManager.release();
			}
		}
	}
	
}

package cn.tedu.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


import org.springframework.stereotype.Repository;


import cn.tedu.domain.User;
import cn.tedu.util.JDBCUtils;
import cn.tedu.util.TransactionManager;

@Repository
public class UserDaoImpl implements UserDao{
	
	@Override
	public void addUser(User user) {
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		//注册数据库驱动
		//获取数据库连接
		try {
			conn=TransactionManager.getConn();
			ps=conn.prepareStatement("insert into user values(?,?,?)");
			ps.setInt(1, user.getId());
			ps.setString(2, user.getName());
			ps.setInt(3, user.getAge());
			ps.executeUpdate();
			//需求:报异常不想让他传入数据库,可以通过事务处理
			//int i=1/0;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}finally{
			JDBCUtils.close(null, ps, rs);
		}
		
	}

	@Override
	public void delUser(int id) {
		Connection conn=null;
		PreparedStatement ps=null;
		try {
			conn=TransactionManager.getConn();
			ps=conn.prepareStatement("delete from user where id=?");
			ps.setInt(1,id);
			ps.executeUpdate();
			//需求:报异常不想让他传入数据库,可以通过事务处理
			//int i=1/0;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}finally{
			JDBCUtils.close(null, ps,null);
		}
	}

	@Override
	public User queryUser(int id) {
		Connection conn=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		//注册数据库驱动
		//获取数据库连接
		try {
			conn=TransactionManager.getConn();
			ps=conn.prepareStatement("select * from user where id=?");
			ps.setInt(1, id);
			rs=ps.executeQuery();
			User user=null;
			if(rs.next()){
				user=new User();
				user.setId(rs.getInt("id"));
				user.setName(rs.getString("name"));
				user.setAge(rs.getInt("age"));
			}
			return user;
			//需求:报异常不想让他传入数据库,可以通过事务处理
			//int i=1/0;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}finally{
			JDBCUtils.close(null, ps, rs);
		}
		
	}
	
}

package cn.tedu.service;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.tedu.anno.Trans;
import cn.tedu.dao.UserDao;
import cn.tedu.domain.User;

@Service
public class UserServiceImpl implements UserService{
	@Autowired
	UserDao userDao=null;
	@Trans
	@Override
	public void addUser(User user){
			userDao.addUser(user);
	}
	@Override
	public void delUser(int id) {
		userDao.delUser(id);
	}
	@Override
	public User queryUser(int id) {
		return userDao.queryUser(id);
	}
}

package cn.tedu.util;

import java.sql.Connection;

//事务管理提交回滚
public class TransactionManager {
	
	private static Connection conn=JDBCUtils.getConn();
	private TransactionManager(){
		
	}
	
	public static void startTran(){
		try {
			conn.setAutoCommit(false);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	} 
	
	public static void commitTran(){
		try {
			conn.commit();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	} 
	
	public static void rollbacktTran(){
		try {
			conn.rollback();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	} 
	public static Connection getConn(){
		return conn;
	}
	public static void release(){
		JDBCUtils.close(conn, null, null);
	}
}

package cn.tedu.util;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JDBCUtils {
	private JDBCUtils(){
		
	}
	private static DataSource datasource=new ComboPooledDataSource();
	public static Connection getConn(){
		
			try {
				return datasource.getConnection();
			} catch (SQLException e) {
				throw new RuntimeException(e); 
			}
		
	}
	public static void close(Connection conn,Statement stat,ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				rs=null;
			}
		}
		if(stat!=null){
			try {
				stat.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				stat=null;
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				conn=null;
			}
		}
	} 
}

package cn.tedu.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import cn.tedu.domain.User;
import cn.tedu.service.UserService;
@Controller
public class UserServlet {
	@Autowired
	UserService userService=null;
	public void addUser(User user){
		userService.addUser(user);
	}
	public void delUser(int id){
		userService.delUser(id);
	}
	public User queryUser(int id){
		return userService.queryUser(id);
	}
}

有线程问题存在(多个线程、同一个共享资源、至少有一个在写,三者有一个都会造成线程问题)
加锁会降低效率所以使用本地线程变量解决此问题
在这里插入图片描述
在这里插入图片描述

package cn.tedu.demo;
//本地线程变量测试
public class Demo1 {
	private static ThreadLocal<String> tl=new ThreadLocal<String>();
	public static void main(String[] args){
		tl.set("hello from main~");//向当前线程内部内部map中存储了键值对
		A();
	}
	public static void A(){
		B();
	}
	public static void B(){
		C();
	}
	public static void C(){
		D();
	}
	public static void D(){
		System.out.println("d..."+tl.get());//从当前线程内部map中取值
		tl.remove();
		
	}
}

修改上述事务项目(SpringDay04_03aop_demo项目)

package cn.tedu.util;

import java.sql.Connection;

//事务管理提交回滚(改进)
public class TransactionManager {
	
	//private static Connection conn=JDBCUtils.getConn();
	private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>(){
		protected Connection initialValue(){
			return JDBCUtils.getConn();
		};
	};
	
	private TransactionManager(){
		
	}
	
	public static void startTran(){
		try {
			tl.get().setAutoCommit(false);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	} 
	
	public static void commitTran(){
		try {
			tl.get().commit();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	} 
	
	public static void rollbacktTran(){
		try {
			tl.get().rollback();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
	} 
	public static Connection getConn(){
		return tl.get();
	}
	public static void release(){
		JDBCUtils.close(tl.get(), null, null);
		tl.remove();
	}
}

4.通过aop进行权限管理
通过aop来进行权限管理,通过自定义注解声明业务方法是否需要进行权限控制,通过注解上属性声明需要什么样的权限
代码实现:

package cn.tedu.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import cn.tedu.enumration.PrivEnum;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PrivAnno {
	PrivEnum[] value();
}

package cn.tedu.aspect;



import java.lang.reflect.Method;
import java.util.Arrays;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import cn.tedu.anno.PrivAnno;
import cn.tedu.enumration.PrivEnum;
import cn.tedu.test.Test01;
@Component
@Aspect
public class PrivAspect {
	@Around("execution(* cn.tedu.service..*.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable{
		Object obj=pjp.getTarget();
		MethodSignature signature=(MethodSignature) pjp.getSignature();
		Method method=signature.getMethod();//接口上的方法
		Method instMethod=obj.getClass().getMethod(method.getName(), method.getParameterTypes());
		if(instMethod.isAnnotationPresent(PrivAnno.class)){
			PrivAnno pano=instMethod.getAnnotation(PrivAnno.class);
			PrivEnum[] privs=pano.value();
			//.判断是否有权限
			if(Arrays.asList(privs).contains(Test01.tl.get())){
				return pjp.proceed();
			}else{
				throw new RuntimeException("权限不够");
			}
		}else{
			return pjp.proceed();
		}
	}
}

package cn.tedu.enumration;

public enum PrivEnum {
	ADMIN,SUPERADMIN,USER;
}

package cn.tedu.service;

import org.springframework.stereotype.Service;

import cn.tedu.anno.PrivAnno;
import cn.tedu.enumration.PrivEnum;

@Service
public class UserServiceImpl implements UserService{
	@PrivAnno({PrivEnum.ADMIN,PrivEnum.SUPERADMIN})
	@Override
	public void add(){
		System.out.println("增加用户...");
	}
	@PrivAnno({PrivEnum.SUPERADMIN})
	@Override
	public void del() {
		System.out.println("删除用户...");
	}
	@Override
	public void queryUser() {
		System.out.println("查询用户...");
		
	}
}

package cn.tedu.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import cn.tedu.service.UserService;
@Controller
public class UserServlet {
	@Autowired
	UserService userService=null;
	public void addUser(){
		userService.add();
	}
	public void delUser(){
		userService.del();
	}
	public void queryUser() {
		userService.queryUser();
	}
	
}

package cn.tedu.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.tedu.enumration.PrivEnum;
import cn.tedu.web.UserServlet;

public class Test01 {
	public static ThreadLocal<PrivEnum> tl=new ThreadLocal<PrivEnum>();
	@Test
	public void test00(){
		new Thread(new Runnable() {
			@Override
			public void run() {
				tl.set(PrivEnum.SUPERADMIN);
				ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
				UserServlet userServlet=(UserServlet) context.getBean("userServlet");
				userServlet.addUser();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				tl.set(PrivEnum.ADMIN);
				ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
				UserServlet userServlet=(UserServlet) context.getBean("userServlet");
				userServlet.delUser();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				tl.set(PrivEnum.USER);
				ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
				UserServlet userServlet=(UserServlet) context.getBean("userServlet");
				userServlet.addUser();
			}
		}).start();
		
		
	}
	
	
	
	//public static PrivEnum role=PrivEnum.ADMIN;
	@Test
	public void test01(){
		
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserServlet userServlet=(UserServlet) context.getBean("userServlet");
		userServlet.addUser();
		
	}
	@Test
	public void test02(){
		
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserServlet userServlet=(UserServlet) context.getBean("userServlet");
		userServlet.delUser();
	}
	@Test
	public void test03(){
		
		ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
		UserServlet userServlet=(UserServlet) context.getBean("userServlet");
		userServlet.queryUser();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值