前言

github: https://github.com/vergilyn/SpringBootDemo

一、AOP

官方demo:https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-aop

1.1 pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
1.2 demo

对aop的properties配置有:

#### AOP
# spring.aop.auto=true # Add @EnableAspectJAutoProxy.
# spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false).

这两个配置都允许注解配置: @EnableAspectJAutoProxy (proxyTargetClass = false,exposeProxy = false),默认值都是false
    代码目录:

代码说明:

1. AopService:被aop增强的class。

AopAspect:aop增强的class。

AopApplication:启动、测试class。

2. 整个demo很简单,实际要用到再去细看AOP也可以。

@Component
public class AopService {
@Value("${aop.name:Dante}")
private String name; public String getMsg() {
return "Hello, " + this.name;
}
}
@Aspect
@Component
public class AopAspect {
@AfterReturning("execution(* com.vergilyn.demo.springboot.aop.*Service.*(..))")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("aop @AfterReturning: " + joinPoint);
}
}
@SpringBootApplication
//开启aop支持; 可properties配置proxyTargetClass、exposeProxy
//@EnableAspectJAutoProxy //(proxyTargetClass = true,exposeProxy = false)
public class AopApplication implements CommandLineRunner {
@Autowired
private AopService aopService; public static void main(String[] args) {
SpringApplication app = new SpringApplication(AopApplication.class);
app.setAdditionalProfiles("aop");
app.run(args);
} @Override
public void run(String... args) {
System.out.println(this.aopService.getMsg());
}
}

aop.name=vergilyn

#### AOP
# spring.aop.auto=true # Add @EnableAspectJAutoProxy.
# spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false).

application-aop.properties

console输出结果:

aop @AfterReturning: execution(String com.vergilyn.demo.springboot.aop.AopService.getMsg())
Hello, vergilyn

二、自定义注解

其实我本来是要做的是:自定义注解注入Logger,所以才顺道写了一下AOP的demo。

需求:

1. 通过注解,注入Logger(org.apache.log4j.Logger)。

说明:

之前注入日志都是在每个类中写代码,ex:

public class XXclass{
private Logger log = Logger.getLogger(XXclass.class);
}

现在想通过自定义注解注入,ex:

public class XXclass{
private Logger log1 = Logger.getLogger(XXclass.class); @Log //自定义注解
private Logger log2;
}

其中log2的效果与log1一样。

实现:

1. 可以通过aop注入。

2. 可以通过实现org.springframework.beans.factory.config.BeanPostProcessor注入;

(其实是一样的,了解spring的就知道Bean的注入都会通过BeanPostProcessor)

代码demo:

注解Log的定义

@Retention(RUNTIME)
@Target(FIELD)
@Documented
@Inherited
public @interface Log { }

注解的实现

@Component
@Aspect
public class LogInjector implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
} public Object postProcessBeforeInitialization(final Object bean,String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException,
IllegalAccessException {
// System.out.println("Logger Inject into :" + bean.getClass());
// make the field accessible if defined private
ReflectionUtils.makeAccessible(field);
if (field.getAnnotation(Log.class) != null) {
Logger log = Logger.getLogger(bean.getClass());
field.set(bean, log);
}
}
});
return bean;
}
}

启动、测试类

@SpringBootApplication
public class AnnotationApplication implements CommandLineRunner{
@Log
private Logger log; public static void main(String[] args) {
SpringApplication app = new SpringApplication(AnnotationApplication.class);
app.setAdditionalProfiles("log");
app.run(args);
} @Override
public void run(String... args) throws Exception {
System.out.println("log : " + log);
log.info("log 注解注入成功. log:" + log);
}
}

输出结果:

log : org.apache.log4j.Logger@24d31b86
2017-03-19 19:44:34.576 INFO 7688 --- [ restartedMain] ication$$EnhancerBySpringCGLIB$$52ae5e8e : log 注解注入成功. log:org.apache.log4j.Logger@24d31b86

三、扩展:spring boot之@Import、@ImportResource

缘由:由于我代码的目录结构是,一个project中根据package不同(因为spring boot默认扫描启动类所在的包,及其子包),测试spring boot的各种功能。

比如图中的*Application.class都是spring boot的启动类。然而我想把前面写的Log注解用在所有的*Application对应的项目中。

这就迁出一个问题:*Application.class只扫描所在的package及其sub-packages。从目录结构可以看到,Log并不能被别的*Application.class扫描到。

所以,要怎么解决呢?

这就需要spring boot提供的注解:@Import、@ImportResource。ex:

@SpringBootApplication
@EnableScheduling //通过@EnableScheduling注解开启对计划任务的支持
//@ImportResource(locations = "ConfigXML/annotation-scan.xml" )
@Import(value = LogInjector.class)
public class TimmerApplication {
public static void main(String[] args) {
SpringApplication.run(TimmerApplication.class, args);
}
}

对于@ImportResource需要通过xml注入bean(就是普通的spring),annotation-scan.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <!-- 扫描公共组件 -->
<context:component-scan base-package="com.vergilyn.demo.annotation" /> </beans>

【spring boot】SpringBoot初学(6)– aop与自定义注解的更多相关文章

  1. Java Spring Boot VS .NetCore (十一)自定义标签 Java Tag Freemarker VS .NetCore Tag TagHelper

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  2. Spring Boot → 08:嵌入式Servlet容器自定义

    Spring Boot → 08:嵌入式Servlet容器自定义

  3. Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute

    Java Spring Boot VS .NetCore (一)来一个简单的 Hello World Java Spring Boot VS .NetCore (二)实现一个过滤器Filter Jav ...

  4. SpringBoot 源码解析 (十)----- Spring Boot的核心能力 - 集成AOP

    本篇主要集成Sping一个重要功能AOP 我们还是先回顾一下以前Spring中是如何使用AOP的,大家可以看看我这篇文章spring5 源码深度解析----- AOP的使用及AOP自定义标签 Spri ...

  5. Spring Boot系列——AOP配自定义注解的最佳实践

    AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...

  6. Spring Boot 2.0 教程 | AOP 切面统一打印请求日志

    欢迎关注微信公众号: 小哈学Java 文章首发于个人网站 https://www.exception.site/springboot/spring-boot-aop-web-request 本节中,您 ...

  7. 用AOP拦截自定义注解并获取注解属性与上下文参数(基于Springboot框架)

    目录 自定义注解 定义切面 获取上下文信息JoinPoint ProceedingJoinPoint 定义测试方法 测试结果 小结 AOP可以用于日志的设计,这样话就少不了要获取上下文的信息,博主在设 ...

  8. Spring Boot(五):Spring Boot的启动器Starter大全及自定义Starter

    现有启动器Starter目录 Spring Boot应用启动器基本的一共有44种,具体如下: 1)spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和 ...

  9. SpringBoot框架:通过AOP和自定义注解完成druid连接池的动态数据源切换(三)

    一.引入依赖 引入数据库连接池的依赖--druid和面向切面编程的依赖--aop,如下所示: <!-- druid --> <dependency> <groupId&g ...

随机推荐

  1. 曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  2. Codeforces 1092 D2 Great Vova Wall (Version 2) (栈)

    题意: 给一排砖,每列的高度$a_i$,问是否可以放1*2的砖,使得n列高度一样,砖只能横着放 思路: 每两个相邻的高度相同的砖可以变成大于等于它的高度的任意高度 所以像这样的 123321 是不满足 ...

  3. 量子计算机编程(一)——QPU编程

    今天要给大家介绍的是这本书<Programming Quantum Computers -- Essential Algorithms and Code Samples>,主要讲如何在量子 ...

  4. Github搜索技巧-如何使用github找到自己感兴趣的项目(转载)

    Github现在不仅仅作为一个版本控制工具,更是一个开源的仓库,里面不但有优秀的开源代码,电子书,还有一些五花八门的项目,有些国家的法律也放在上面,作为程序员如何找到自己感兴趣的项目就非常重要了! 欢 ...

  5. 编辑crontab添加Linux计划任务

    在做实验楼的比赛时的题目 用到了crontable 1. 为用户shiyanlou添加一个计划任务 2. 每天凌晨2点定时执行 3. 将/var/log/dpkg.log /var/log/mysql ...

  6. Bound Method and Unbound Method - 绑定方法 与 非绑定方法

    Bound Method and Unbound Method 通常有两种方法对类的方法(instance.method)/属性(class.attribute)进行引用, 一种称做 Bound Me ...

  7. Python3(二) 表示‘组’的概念与定义

    现实世界中总存在一组一组的事物, 一.列表的定义 type(['hello','world',1,9,True,False]) = <class 'list'> type([[1,2,3, ...

  8. python 实现 跳一跳游戏 代码解析

    这个代码实现的是   手动点击起点 和 终点  ,程序自动判断距离.触屏时间  完成跳跃 原理(摘自项目说明页面):1. 将手机点击到“跳一跳”小程序界面:2. 用Adb 工具获取当前手机截图,并用a ...

  9. css架构技巧

    1. 写一个reset.css 用于清除浏览器标签默认样式并定义全局样式,这样就不会因为浏览器默认样式出现问题,因为不同浏览器的默认样式还是不一样的

  10. MySQL常用语法总结

    一,学习mysql的前戏 1:基础入门命令 show databases: #查看当前MySQL中的所有数据库 create 数据库名: #创建新的数据库 use 数据库名: #使用该数据库 show ...