目录
一.什么是Spring框架
是一个轻量级的企业级应用框架
企业应用开发的"一站式"选择,贯穿于表现层、业务层、持久层
Spring框架是一个开源的Java应用程序框架,它提供了一系列的功能和组件,能够帮助开发者快速构建可扩展的企业级应用程序
Spring框架由多个模块组成,每个模块都提供了一个特定的功能,包括核心容器、数据访问、Web、AOP、消息、测试等。
二.使用Spring的优点
优点:
低侵入式设计
独立于各种应用服务器
依赖注入特性将组件关系透明化,降低耦合度
面向切面编程特性允许将通用任务进行集中式处理
与第三方框架的良好整合
三.Spring体系结构
四.Spring两大核心技术
控制反转(IoC:Inversion of Control)/依赖注入(DI:Dependency Injection)
面向切面编程(AOP:Aspect Oriented Programming)
控制反转(IoC) 创建对象的控制权转移,是一种程序设计思想
依赖注入(DI) 将依赖的对象注入到需要的类中去,是"控制反转"设计思想的具体实现方式
面向切面编程(AOP)(如下参考)
public class UserServiceImpl implements UserService {
private static final Logger log = Logger.getLogger(UserServiceImpl.class);
public boolean save(User user){
log.info(" 添加用户" + user.getUsername());//记录日志
SqlSession sqlSession = null;
boolean flag = false;
try{ //异常处理
sqlSession = MyBatisUtil.createSqlSession();
if(sqlSession.getMapper(userMapper.class).add(user) > 0)
flag = true;
sqlSession.commit();//事务控制
log.info(" 成功添加用户" + user.getUsername());
} catch (Exception e){
log.error(" 添加用户" + user.getUsername() + " 失败", e); //记录日志
sqlSession.rollback(); //事务控制
flag = false;
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
return flag;
}
}
AOP目标
让我们专注于业务功能处理
AOP原理
将复杂的需求分解出不同方面,将不同对象、不同模块之间的共同业务集中解决 通过动态代理的方式,把抽离出来的共性代码"织入"到业务代码中,实现对原有代码的增强处理
下面是一个Spring AOP的完整例子,实现了一个简单的日志记录功能:
首先,定义一个接口和实现类:
public interface UserService {
void addUser(String name);
void updateUser(String name);
void deleteUser(String name);
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("Add user: " + name);
}
@Override
public void updateUser(String name) {
System.out.println("Update user: " + name);
}
@Override
public void deleteUser(String name) {
System.out.println("Delete user: " + name);
}
}
然后,定义一个切面类,并在其中定义一个日志记录方法:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.UserService.*(..))")
public void log(JoinPoint joinPoint) {
System.out.println("Logging " + joinPoint.getSignature().getName() + " method");
}
}
其中,@Aspect用于将该类标记为切面类,@Before("execution(* com.example.UserService.*(..))")表示在UserService接口中的所有方法执行之前,执行log方法。
最后,在Spring配置文件中加入AOP的配置:
<!-- 开启AOP自动代理 -->
<aop:aspectj-autoproxy />
<!-- 注册切面 -->
<bean id="loggingAspect" class="com.example.LoggingAspect" />
现在,可以通过调用UserService接口中的方法来测试AOP的效果:
@Autowired
private UserService userService;
@Test
public void test() {
userService.addUser("Alice");
userService.updateUser("Bob");
userService.deleteUser("Charlie");
}
执行结果如下:
Logging addUser method
Add user: Alice
Logging updateUser method
Update user: Bob
Logging deleteUser method
Delete user: Charlie
可见,在AOP的作用下,每次方法执行前都会输出一条日志记录。
小结:
五.异常抛出增强、最终增强、环绕增强的使用方法
异常抛出增强:
异常抛出增强是 AOP 中的一个通知类型,用于在方法抛出异常时执行一些处理逻辑。它的使用方法如下:
@Aspect
public class ExceptionHandlerAspect {
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void handleException(Exception ex) {
// 处理逻辑
}
}
在上面的例子中,@AfterThrowing
声明了一个异常抛出增强,它的 pointcut
属性表示匹配 com.example.service
包下的所有方法,throwing
属性表示在抛出异常时需要传递一个 Exception
类型的参数。在处理逻辑中,可以获得抛出的具体异常,并进行相应的处理。
最终增强:
最终增强是 AOP 中的一个通知类型,它的作用是在方法执行结束后执行一些操作,无论方法是否抛出异常。最终增强的使用方法如下:
@Aspect
public class FinallyAspect {
@After("execution(* com.example.service.*.*(..))")
public void after() {
// 处理逻辑
}
}
在上面的例子中,@After
声明了一个最终增强,它的 pointcut
属性表示匹配 com.example.service
包下的所有方法。在处理逻辑中,可以编写任何需要在方法结束后执行的操作。
环绕增强:
环绕增强是 AOP 中最为强大的通知类型,它可以在方法执行前后以及抛出异常时执行任何操作。环绕增强的使用方法如下:
@Aspect
public class AroundAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 方法执行前的处理逻辑
Object result = joinPoint.proceed();
// 方法执行后的处理逻辑
return result;
}
}
在上面的例子中,@Around
声明了一个环绕增强,它的 pointcut
属性表示匹配 com.example.service
包下的所有方法。在处理逻辑中,使用 ProceedingJoinPoint
对象的 proceed()
方法调用目标方法,并获得方法执行结果。在方法执行前后可以编写任何需要执行的操作。如果方法抛出异常,将会继续向上抛出,由异常抛出增强来处理。
六.构造注入
构造注入是一种针对应用程序进行攻击的注入方式,旨在让攻击者可以执行恶意代码或访问敏感信息。它是通过构建特定的输入字符串来触发应用程序中的漏洞,从而实现对应用程序的控制。具体来说,构造注入是指利用应用程序的输入参数,通过构造恶意输入,使应用程序的执行逻辑发生改变,从而达到攻击的目的。常见的构造注入攻击包括 SQL 注入、命令注入、XML 注入等。
在构造注入攻击中,攻击者会构造一些特殊的输入,以欺骗应用程序,使其执行恶意代码或者访问敏感信息。攻击者可以通过构造注入攻击来窃取敏感信息,如用户名、密码、信用卡号等,并可能导致更严重的后果,如服务器崩溃、数据丢失等。为了预防构造注入攻击,开发人员应该采取安全编程实践,如使用参数化查询等方式来缓解此类安全漏洞。此外,定期进行安全测试,也是保护应用程序免受构造注入攻击的重要措施之一。
七.使用注解的方式实现IoC
使用注解的方式实现IoC(Inversion of Control)是一种常用的Spring框架IoC实现方式。注解是Java语言的一种扩展方式,可以通过注解的方式来描述对象的属性和行为,从而实现对象的依赖注入。以下是使用注解的方式实现IoC的几个关键步骤:
-
标记需要注入的对象,使用注解来描述对象的属性和行为。
-
创建IoC容器,容器会扫描所有带有特定注解的类,将这些类实例化并装配到容器中。
-
定义依赖关系,通过注解来描述对象之间的依赖关系,容器会自动管理这些依赖关系,实现对象的自动装配。
例如,下面是一个使用注解方式实现IoC的示例代码:
public class UserController {
@Autowired
private UserService userService;
public void addUser(User user) {
userService.addUser(user);
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void addUser(User user) {
userDao.insert(user);
}
}
@Repository
public class UserDao {
public void insert(User user) {
// 插入用户数据
}
}
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
在上述例子中,使用了@Autowired注解来标记需要注入的对象,@Service和@Repository注解用来标记服务和数据访问层的组件。@ComponentScan注解则用来告诉容器扫描哪些包下的组件进行装配。通过以上的注解配置,可以实现IoC容器对UserController、UserService和UserDao等组件的自动管理和依赖注入。
总的来说,使用注解的方式实现IoC可以减少开发人员的代码量,提高开发效率,同时也可以更加方便地管理组件之间的依赖关系。
八.使用注解的方式实现AOP
在Java中,可以使用注解的方式来实现AOP,具体步骤如下:
- 定义注解
首先,需要定义一个自定义注解,用来标记需要进行AOP的方法。这个注解可以包含一些元数据,例如切点表达式等。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAopAnnotation {
String value() default "";
}
- 编写切面类
接下来,需要编写切面类,这个类实现了AOP的核心逻辑,例如在方法执行前后进行日志记录、权限验证等。在切面类中使用@Before、@After等注解来表示要在方法执行前后执行的逻辑。
@Aspect
@Component
public class MyAopAspect {
@Before("@annotation(com.example.MyAopAnnotation)")
public void beforeAdvice() {
System.out.println("Before advice...");
}
@After("@annotation(com.example.MyAopAnnotation)")
public void afterAdvice() {
System.out.println("After advice...");
}
}
其中,@Aspect注解表示这个类是一个切面类,@Before、@After注解表示对应的切点逻辑。
- 在目标方法上添加注解
最后,在需要进行AOP的目标方法上添加自定义注解。
@MyAopAnnotation
public void doSomething() {
// ...
}
这样,在目标方法执行前会先执行切面类中定义的@Before逻辑,然后执行目标方法,最后执行切面类中定义的@After逻辑。
以上就是使用注解的方式实现AOP的基本流程。当然,在实际应用中还需要考虑一些其他因素,例如切面类的执行顺序、异常处理等。