浅入java架构-Aspect-日志处理

浅入java架构-Aspect-日志处理

很多的架构师,或者高级程序员在面试新人的时候,都会在架构方面问一个非常常见且十分经典的知识:那就是怎样设计系统日志输出程序。毫无疑问,面试官想了解面试者的spring中aspect的编程思想及在程序的运用,从而了解面试者在以前的项目当中所担任的项目角色和所做的事情范围。

闲话少说,今天笔者就spring中aspect,也就是面向切面编程,与广大java爱好者一起探讨下,在项目中日志打印的设计;

六个步骤即可完成日志打印:

一、定义注解(annocation):AutoLogMethod

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Component
public @interface AutoLogMethod {
	String value() default "";
}

二、定义注解(annocation):MethodParam

@Retention(RetentionPolicy.RUNTIME)
@Target({java.lang.annotation.ElementType.PARAMETER})
@Documented
@Component
public @interface MethodParam{
	String value() default "param->";
}

三、创建日志输入工具类:LogUtil

public class LogUtil {
	private static final Logger logger = LoggerFactory.getLogger(LogUtil.class);
	public static void error(final String message) {
		if (logger != null) {
			logger.error(message);
		} else {
			System.err.printf("ERROR: %s\n", message);
		}
	}
	public static void error(final String message, final Throwable t) {
		if (logger != null) {
			logger.error(message, t);
		} else {
			String err = message  + "\r\n" + ExceptionUtils.getRootCauseMessage(t);
			System.err.printf("ERROR: %s\n", err);
		}
	}
	public static void error(String message, Throwable t, Object... obj) {
		String err = String.format(message, obj) ;
		error(err,t);
	}
	
	public static void info(final String message) {
		if (logger != null) {
			logger.info(message);
		} else {
			System.err.printf("INFO: %s\n", message);
		}
	}

	public static void info(String message, Object... obj) {
		info(String.format(message, obj));
	}
}

四、创建切面(Aspect):LogAspect

    (1)、引入Aspectj所需相关jar支持

                 pom.xml

                <dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.6.12</version>
		</dependency>

    (2)、spring管理启动Aspectj,这只自动启动

                <aop:aspectj-autoproxy proxy-target-class="true"/>

    (3)、创建切面(Aspect):LogAspect

                注意:因为是日志打印处理,所以给该切面的优先级设置最高,即@Order(-1)

@Aspect
@Component
@Order(-1)
public class LogAspect {

	@Pointcut("@annotation(com.jd.jr.hd.jsf.common.annocation.AutoLogMethod)")
	public void autoLog() {
	}

	@Around(value = "autoLog()")
	public Object aroundLog(ProceedingJoinPoint pjp) throws Throwable {
		Field filed = pjp.getClass().getDeclaredField("methodInvocation");
		filed.setAccessible(true);
		Object methodInvocation = (Object) filed.get(pjp);

		Method method = methodInvocation.getClass().getMethod("getMethod");
		Method m = (Method) method.invoke(methodInvocation);
		String mn = pjp.getTarget().getClass().getName() + '.' + m.getName();
		AutoLogMethod autoLogMethod = m.getAnnotation(AutoLogMethod.class);
		StringBuffer sb = new StringBuffer();
		if (autoLogMethod != null) {
			Annotation annotation[][] = m.getParameterAnnotations();
			for (int i = 0; i < pjp.getArgs().length; i++) {
				String paramName = null;
				for (Annotation a : annotation[i]) {
					if (a.annotationType() == MethodParam.class) {
						paramName = ((MethodParam) a).value();
						break;
					}
				}
				if (paramName != null) {
					sb.append('[').append(paramName);
					sb.append(':');
					sb.append(pjp.getArgs()[i] == null ? "" : pjp.getArgs()[i].toString()).append(']');
				}
			}
			LogUtil.info("autoLog %s --> %s请求	%s", mn, autoLogMethod == null ? "" : autoLogMethod.value(), sb.toString());
		}
		try {
			Object retVal = pjp.proceed();
			LogUtil.info("autoLog %s --> %s响应	%s", mn, autoLogMethod == null ? "" : autoLogMethod.value(), retVal);
			return retVal;
		} catch (Throwable t) {
			LogUtil.error(String.format("autoLog %s --> %s异常	%s", mn, autoLogMethod == null ? "" : autoLogMethod.value(), sb.toString()), t);
			throw t;
		}
	}
}

五、创建一个服务供测试调用:LogService

@Service
public class LogService {
	
	@AutoLogMethod(value = "autoLogTest")
	public void autoLogTest(@MethodParam("参数") LoginReq req) throws ServiceException {
		System.out.println("----------------------autoLogTest打印成功!-----------------------");
	}
	
	public String logTest(String name) {
		System.out.println("----------------------logTest打印成功!-----------------------");
		return name+"返回了";
	}
}

六、创建JUnit测试启动类:LogTest.autoLogtest()

@Service
public class LogService {
	
	@AutoLogMethod(value = "autoLogTest")
	public void autoLogTest(@MethodParam("参数") LoginReq req) throws ServiceException {
	    if("".equals(req.getUserId())) {
            throw new ServiceException("-1", "用户名不能为空");
        }
        if("".equals(req.getPassword())) {
            throw new ServiceException("-2", "密码不能为空");
        }
		System.out.println("----------------------autoLogTest打印成功!-----------------------");
	}
	
	public String logTest(String name) {
		System.out.println("----------------------logTest打印成功!-----------------------");
		return name+"返回了";
	}
}


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答这个问题。以下是Java项目中Bank类的定义: ```java public class Bank { private int accountId; private String accountName; private double balance; public Bank(int accountId, String accountName, double balance) { this.accountId = accountId; this.accountName = accountName; this.balance = balance; } public int getAccountId() { return accountId; } public String getAccountName() { return accountName; } public double getBalance() { return balance; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) { balance -= amount; } public void transfer(Bank toAccount, double amount) { withdraw(amount); toAccount.deposit(amount); } } ``` 接下来,我们可以使用三层架构来实现银行业务处理。首先,我们需要定义一个业务逻辑层(Service Layer),用于处理业务逻辑。以下是一个简单的实现: ```java public class BankService { private BankDao bankDao; public BankService(BankDao bankDao) { this.bankDao = bankDao; } public void deposit(int accountId, double amount) { Bank account = bankDao.getAccount(accountId); account.deposit(amount); bankDao.updateAccount(account); System.out.println("Deposit: " + amount); System.out.println("Account Name: " + account.getAccountName()); System.out.println("Balance: " + account.getBalance()); } public void withdraw(int accountId, double amount) { Bank account = bankDao.getAccount(accountId); account.withdraw(amount); bankDao.updateAccount(account); System.out.println("Withdraw: " + amount); System.out.println("Account Name: " + account.getAccountName()); System.out.println("Balance: " + account.getBalance()); } public void transfer(int fromAccountId, int toAccountId, double amount) { Bank fromAccount = bankDao.getAccount(fromAccountId); Bank toAccount = bankDao.getAccount(toAccountId); fromAccount.transfer(toAccount, amount); bankDao.updateAccount(fromAccount); bankDao.updateAccount(toAccount); System.out.println("Transfer: " + amount); System.out.println("From Account Name: " + fromAccount.getAccountName()); System.out.println("From Account Balance: " + fromAccount.getBalance()); System.out.println("To Account Name: " + toAccount.getAccountName()); System.out.println("To Account Balance: " + toAccount.getBalance()); } } ``` 接下来,我们需要定义一个数据访问层(Data Access Layer),用于访问数据库。以下是一个简单的实现: ```java public class BankDao { private Map<Integer, Bank> accounts = new HashMap<>(); public BankDao() { accounts.put(1, new Bank(1, "Alice", 1000)); accounts.put(2, new Bank(2, "Bob", 2000)); } public Bank getAccount(int accountId) { return accounts.get(accountId); } public void updateAccount(Bank account) { accounts.put(account.getAccountId(), account); } } ``` 最后,我们需要定义一个切面类(Aspect),用于实现日志打印的增强处理。以下是一个简单的实现: ```java public class LoggingAspect { public void before(JoinPoint joinPoint) { System.out.println("Before " + joinPoint.getSignature().getName()); } public void afterReturning(JoinPoint joinPoint, Object result) { System.out.println("After " + joinPoint.getSignature().getName()); if (result instanceof Bank) { Bank account = (Bank) result; System.out.println("Account Name: " + account.getAccountName()); System.out.println("Balance: " + account.getBalance()); } } } ``` 现在,我们可以使用以上三个类来实现银行业务处理。以下是一个简单的测试: ```java public class BankTest { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); BankService bankService = context.getBean(BankService.class); bankService.deposit(1, 100); bankService.withdraw(2, 200); bankService.transfer(1, 2, 300); } } ``` 输出结果如下: ``` Before deposit Deposit: 100.0 Account Name: Alice Balance: 1100.0 After deposit Account Name: Alice Balance: 1100.0 Before withdraw Withdraw: 200.0 Account Name: Bob Balance: 1800.0 After withdraw Account Name: Bob Balance: 1800.0 Before transfer Transfer: 300.0 From Account Name: Alice From Account Balance: 800.0 To Account Name: Bob To Account Balance: 2100.0 After transfer Account Name: Alice Balance: 800.0 Account Name: Bob Balance: 2100.0 ``` 以上就是使用三层架构实现银行业务处理的简单示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值