一、依赖注入
1.导包
4.0.0
<groupId>cn.itsource</groupId>
<artifactId>spring-day2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/test/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
2.构造参数注入
方案一:根据构造器参数的顺序(索引)
!-- 按照索引注入,索引开始为0 -->
1
2
3
4
5
方案二:根据构造器参数的名称
2.第一步:配置让Spring扫描类与支持注解
<context:component-scan base-package=“cn.itsource._03_anno” />
<context:annotation-config />
3.第二步:在类里面加上注解
.Dao
@Repository
public class UserDao {
public void save(){
System.out.println(“保存数据xxxx…”);
}
}
.Service
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void save(){
userDao.save();
}
}
.Action
/**
Spring 的Controller 实例化默认是单例.
每次请求 controller 就会只使用这一个对象.
*/
@Controller
@Scope(“prototype”)//使用Spring的@Scope(“prototype”)注解,让单例变成多例.
public class UserAction {
@Autowired
private UserService userService;
public String save(){
userService.save();
return “success”;
}
}
4.注解配置bean的名称
4.1.接口有两个实现(可能性比较少)
成之后,大家注意,现在的配置还有一个问题,比如说我按真实情况来一个Dao接口,然后这个接口有两个实现,现在就会出问题
IUserDao (UserJdbcDaoImpl/UserJpaDaoImpl)
而我们声明的时候就是使用了IUserDao
@Service
public class UserService {
@Autowired
private IUserDao userDao;
public void save(){
userDao.save();
}
}
此时会就出错:因为Spring不知道你用的是哪一个dao的实现
4.2.解决的方案:为dao生成的bean加上名称,我们在调用的时候确定名称即可。
@Repository(“userJdbcDao”)
public class UserJdbcDaoImpl implements IUserDao{
public void save(){
System.out.println(“保存数据xxxx…”);
}
}
@Repository(“userJpaDao”)
public class UserJpaDaoImpl implements IUserDao{
public void save(){
System.out.println(“保存数据xxxx…”);
}
}
5.调用名称两套方案:
方案一:使用@Autowired
@Service
public class UserService {
@Autowired
@Qualifier(“userJdbcDao”)
private IUserDao userDao;
public void save(){
userDao.save();
}
}
方案二:使用@Resource
@Service
public class UserService {
@Resource(name=“userJpaDao”)
private IUserDao userDao;
public void save(){
userDao.save();
}
}
如果你用的是Spring的注解,尽量全部使用Spring的标签
三、Spring的AOP
1.AOP概述
定义: 面向切面编程(面向方面编程)
AOP可以用于事务管理,日志管理,性能监测等地方
AOP应用场景:
咱们写代码都知道,如果多个类出现了相同的代码,就应该抽取一个父类,然后把这些公共的代码都写在父类中。
比如说老鹰,鸽子,麻雀,它们都可以翱翔于天际,
2.Xml版实现AOP
1.添加jar文件
aop,aspects
spring-framework-4.1.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0\com.springsource.org.aopalliance-1.0.0.jar
spring-framework-4.1.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE\com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
2.添加aop命名空间
xmlns:aop=“http://www.springframework.org/schema/aop”
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
spring.xml
<?xml version="1.0" encoding="UTF-8"?><!-- 业务增强的bean -->
<bean id="transactionManager" class="cn.itsource._09_SpringAOP_XML.transaction.TransactionManager"/>
<!-- 被代理对象 -->
<bean id="userServiceImpl" class="cn.itsource._09_SpringAOP_XML.service.UserServiceImpl"></bean>
<!--
xml配置AOP
-->
<aop:config>
<!--
expression 表达式
声明一个切点【何时何地】
第一个星号:表示任意返回类型
cn.itsource._09_SpringAOP_XML.service:包名称
包名称后面的两个点..:两个点表示当前包或者当前包的子包,不限制包的级别
第二个星号:任意类名称
第三个星号:任意方法名称
(..):任意参数列表
-->
<aop:pointcut id="myPointcut" expression="execution(* cn.itsource._09_SpringAOP_XML.service..*.*(..))"/>
<!-- 切面通知:要做什么 业务逻辑增强 -->
<aop:aspect ref="transactionManager">
<!--
aop:before 前置通知:表示在你调用myPointcut指向的方法之前调用 transactionManager的bean对象的begin方法
-->
<!--<aop:before method="begin" pointcut-ref="myPointcut"/>-->
<!-- aop:after-returning 后置通知 -->
<!--<aop:after-returning method="commit" pointcut-ref="myPointcut"/>-->
<!-- aop:after-throwing 异常通知 相当于catch语句块内部执行的事务回滚 -->
<!-- <aop:after-throwing method="rollback" pointcut-ref="myPointcut"/>-->
<!-- aop:after 最终通知 相当于finally语句块内部要执行的关闭资源等逻辑代码 -->
<!--<aop:after method="finalM" pointcut-ref="myPointcut"/>-->
<!-- aop:around 环绕通知【推荐使用】,用来代替上面的四个通知,自定义增强业务逻辑 -->
<aop:around method="around" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>
service
public interface IUserService {
void test();
void add();
}
@Service
public class UserServiceImpl implements IUserService {
@Override
public void add() {
//int i = 10/0;
System.out.println(“add方法”);
}
@Override
public void test() {
System.out.println(“11111111111”);
}
}
public class TransactionManager {
public void begin(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
public void rollback(){
System.out.println("事务回滚");
}
public void finalM(){
System.out.println("释放资源");
}
/**
* 环绕通知的业务增强:自定义增强业务逻辑
* @param joinPoint
* @return
*/
public Object around(ProceedingJoinPoint joinPoint){
Object obj = null;
try {
//执行目标方法之前 开启事务
this.begin();
//执行目标方法
obj = joinPoint.proceed();
//执行目标后 提交事务
this.commit();
} catch (Exception e) {
e.printStackTrace();
//事务回滚
this.rollback();
} catch (Throwable throwable) {
throwable.printStackTrace();
//事务回滚
this.rollback();
} finally {
//关闭资源
this.finalM();
}
return obj;
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:cn/itsource/_09_SpringAOP_XML/test/spring.xml”)
public class SpringAOPTest {
@Autowired
private IUserService userService;
@Test
public void test() throws Exception {
System.out.println(userService);
System.out.println(userService.getClass());//com.sun.proxy.$Proxy15
userService.test();
userService.add();
}
}
3.注解版
spring.xml
<!-- 扫描包 -->
<context:component-scan base-package="cn.itsource._10_SpringAOP_Annotation"/>
<!-- 开启注解支持【默认就是开启的】 -->
<context:annotation-config/>
<!-- 自动生成代理对象 -->
<aop:aspectj-autoproxy/>
service层同上
TransactionManager:
package cn.itsource._10_SpringAOP_Annotation.transaction;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect//@Aspect 表示当前类是一个切面
public class TransactionManager {
//自定义一个切点【代替了xml配置的aop:pointcut标签】
@Pointcut("execution(* cn.itsource._10_SpringAOP_Annotation.service..*.*(..))")
public void aaa(){}
/**
* aaa()相当于xml配置文件的aop:pointcut标签的id属性
*/
//@Before("aaa()")
public void begin(){
System.out.println("开启事务");
}
//@AfterReturning("aaa()")
public void commit(){
System.out.println("提交事务");
}
public void rollback(){
System.out.println("事务回滚");
}
public void finalM(){
System.out.println("释放资源");
}
/**
* 环绕通知的业务增强:自定义增强业务逻辑
* @param joinPoint
* @return
*/
@Around("aaa()")
public Object around(ProceedingJoinPoint joinPoint){
Object obj = null;
try {
//执行目标方法之前 开启事务
this.begin();
//执行目标方法
obj = joinPoint.proceed();
//执行目标后 提交事务
this.commit();
} catch (Exception e) {
e.printStackTrace();
//事务回滚
this.rollback();
} catch (Throwable throwable) {
throwable.printStackTrace();
//事务回滚
this.rollback();
} finally {
//关闭资源
this.finalM();
}
return obj;
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:cn/itsource/_10_SpringAOP_Annotation/test/spring.xml”)
public class SpringAOPTest {
@Autowired
private IUserService userService;
@Test
public void test() throws Exception {
System.out.println(userService);
System.out.println(userService.getClass());//com.sun.proxy.$Proxy15
//userService.test();
userService.add();
}
}
总结
AOP是面向切面编程,是对咱们OOP的一个补充,Spring的Aop允许咱们在方法的前后加上相应的功能增强。
Spring的Aop是使用代理模式完成的,如果是有接口的类,使用JDK代理模式,如果没有接口的类,使用CGLIB代理模式。
咱们自己使用AOP太麻烦,Spring让我们通过简单的配置即可完成AOP。
第一种配置:XML 第二种配置:注解
配置的时候注意找到何时(方法前后,异常),何地(哪些类的哪些方法),做什么(安全中是添加事务)