Spring容器介绍
Spring IoC
Spring
框架实现依赖IOC
原则(依赖注入), 相比Bean
直接构建对象, Spring
框架则根据Bean
之间的依赖创建对象, 并注入到Bean
中, 对于传统的代码, 常见下面写法
public UserServiceImpl implements UserService {
private CreditUserService creditUserService = new CreditUserService();
public void order(...){
creditUserService.addCredit(5);
}
}
或者封装一下工厂类
private CreditUserService creditUserService = ServiceFactory.getService(CreditUserService.class);
在Spring
中, 如果你的Bean
是通过Spring
管理的, Spring
框架来帮助你完成这些事情, 开发人员只是需要声明依赖关系
@Service
public UserService {
@Autowired
private CreditUserService creditUserService;
public void order (...) {
...
creditUserService.addCredit(5);
}
}
Bean
通过注解@Service
声明一个Spring
管理的Bean
, Spring
容器会扫描classpath
下的所有类, 找到带有@Service
注解的UserService
类, 并根据Spring
注解对其进行初始化和增强, 如果发现此类属性, creditUserService
也有注解@Autowired
, 则会从Spring
容器中查找一个已经初始化好的CreditUserService
, 如果没有会将其初始化
Spring常用注解
- Controller: 声明此类是一个
MVC
类, 通常与RequestMapping
一起使用@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/get/{id}") public String getUser(@PathVariable String id){ ... } }
- Service: 声明此类是一个业务类, 通常与
@Transactional
一起使用@Service @Transactional public class UserServiceImpl implements UserService { public void order(...){ ... } }
- Repository: 声明此类是一个数据库或者其他
NoSQL
访问类@Repository public class UserDao implements CurdDao<User, String> { }
- ResetController: 同
Controller
, 用于REST
服务 - Component: 声明此类是一个
Spring
管理的类 - Configuration: 声明此类是一个配置类, 通常与
Bean
配合使用// DataSourceConfig为一个容器配置类 @Configuration public class DataSourceConfig { @Bean(name = "dataSource") public DataSource dataSource(Environment env) { HiKariDataSource ds = new HiKariDataSource(); ds.setJdbcUrl(env.getProperty("spring.datasource.url")); db.setUsername(env.getProperty("spring.datasource.username")); db.setPassword(env.getProperty("spring.datasource.password")); db.setDirverClassName(env.getProperty("spring.datasource.driver-class-name")); return db; } }
- Bean: 作用在方法上, 声明该方法执行的结果是一个
Spring
容器管理的Bean
Bean注解详解
Spring
负责实例化Bean
, 开发者可以提供一系列的回调函数, 用于进一步配置Bean
, 其中包含@PostConstruct
(初始化)注解和@PreDestory
(待销毁)
@Component
public class ExampleBean {
@PostConstruct
public void init() {}
}
public class ExampleBean {
@PreDestory
public void cleanup() {}
}
Spring
还提供了其他方法为Bean
周期提供回调, 可以实现InitializingBean
接口的afterPropertiesSet()
初始化Bean
,和实现DisposableBean
的destroy()
来销毁Bean
Spring
有两种方式可以引入Bean
, 根据名字和根据类型
根据名字引用Bean
定义
@Service
@Qualifier("exampleBean")
public class ExampleBean {}
引用
@Service
public AnotherExampleBean{
@Qualifier("exampleBean") ExampleBean bean;
}
根据类型引用Bean
定义
@Service
public class ExampleBean{}
引用
@Service
public class AnotherExampleBean{
@Autowried ExampleBean bean;
}
Spring AOP
AOP几点概念
- Aspect:
Aspect
声明了类似于Java
中的类声明, 在Aspect
中会包含一些Pointcut
和Advice
- Joint Point: 表示在程序中明确定义的点, 包括方法调用, 对类成员调用, 以及异常处理程序块执行
Spring
中的Joint point
只支持方法调用 - Pointcut: 表示一组
Joint point
, 如方法名, 参数类型, 返回类型, 这些Joint point
通过逻辑关系组合起来, 它定义了对应的Advice
将要发生的地方,Pointcut
就是一种表达式, 来判断Joint point
方法调用中执行Advice
操作 - Advice: 定义了在
Pointcut
里面定义的程序点具体需要做的操作, 他通过before
,around
,after
(return
,throw
,finally
), 来区别是在哪一个Joint point
之前或者之后要调用的代码
- before: 在执行方法前调用Advice
, 譬如cache
需要判断是否有记录存在
- around: 环绕通知再, 执行之前呵之后调用Advice
- after: 在执行方法之后调用Advice
,after return
正常返回时调用,after throw
失败时调用 - AOP Proxy:
AOP Proxy
也是Java
对象,由AOP
框架创建, 用来完成上述动作 - Weaving: 实现上述切片编程的代码植入, 可在编译时通过
AspectJ Compiler
也可以在运行时刻,Spring
框架都是在运行时刻生成代理
SpringBoot 中使用 AOP
引入AOP
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
用法
import org.aspectj.lang.ProcessdingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;
@Configuration
@Aspect
public class AOPConfig {
@Around("@within(org.springframework.stereotype.Controller)")
public Object simpleAop(final ProceedingJoinPoint pjp) throws Throwable {
try {
Object[] agrs = pjp.getArgs();
System.out.println("args:" + Arrays.asList(args));
// 调用原有方法
Object o = pjp.proceed();
System.out.println("return :" + o);
return o;
} catch (Throwable e) {
throw e;
}
}
}
代码解析
- @Configuration: 声明这是一个
Spring
管理配置Bean
, 可以理解为引起Spring
的注意 - @Aspect: 声明了这是一个切面类
- @Around: 声明了一个表达式, 描述要植入的特性,
@within
表示目标类型带有注解, 参数为org.springframework.stereotype.Controller
这意味着,Spring
的这个Controller
方法在被调用时, 都会执行@Around
的方法simpleAop
- simpleAop: 用来植入代码, 七参数为
ProceedingJoinPoint
, 上面实例将参数方法取出来, 打印到控制台 - pjp.proceed: 通常情况下, 执行完切面代码, 还需要继续执行应用代码,
proceed()
方法则会继续调用原有业务逻辑, 并将返回对象正常返回
AOP常用表达式
execution(public * *(..)) // 所有`public`方法, 后面星号代表路径名和方法名字
execution(\* set\*(..)) // 所有`set`开头的方法
execution(public set*(...)) // 所有以`set`开头的`public`方法
execution(public com.xyz.service.* set*(...)) // 位于`com.xyz.service`包下所有以`set`开头的`public`方法
target(com.xyz.service.CommonService) // // 所有实现了`CommonService`接口的类和方法
@target(com.springframework.transaction.annotation.Transactional) // 所有`@Transactional`注解的方法
@within(org.springframework.stereotype.Controller) // 类型声明了所有`@Controller`注解的所有方法