Spring
Spring三大核心容器:Beans,Core,Context
Spring中两大核心技术,ICO(控制反转/依赖注入),AOP(面向切面编程)
1. 基本配置
pom.xml 引入Spring与SpringMVC的Jar包:
<properties>
<spring.version>4.0.2.RELEASE</spring.version>
</properties>
<!-- spring框架包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
创建配置文件Spring-config.xml
<!--头部信息-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
2. IOC 控制反转/依赖注入
2.1 控制反转
其实就是把new对象放到了配置文件里
- 将组件对象的控制权从代码本身转移到外部容器
- 组件化的思想:分离关注点,使用接口,不再关注实现
- 依赖的注入:将组件的构建和使用分开
bean:new操作 id="建议使用类名首字母小写" class="你要new 的类的完整路径"
<!-- new HelloWorld() -->
<bean id="helloWorld" class="com.hz.pojo.HelloWorld">
<!-- new HelloWorld().setName("张三") -->
<property name="name" value="张三"/>
<!-- new HelloWorld().setAge(24)-->
<property name="age" value="24"/>
</bean>
读取配置文件并运行
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring1.xml");
UserService userService=(UserService)applicationContext.getBean("userServiceImpl");
String abc= userService.find();
System.out.println(abc);
2.2 依赖注入
指 Spring 创建对象的过程中,将对象依赖属性(简单值,集合,对象)通过配置设值给该对象
引入另一个bean(使用ref属性)
dao层:
public class UserDaoImpl implements UserDao {
String aaa;
public String find(){
System.out.println("11111"+this.aaa);
return "22222";
}
public void setAaa(String aaa) {
this.aaa = aaa;
}
}
service层:
public class UserServiceImpl implements UserService {
UserDao userDao;
@Override
public String toString() {
return "UserServiceImpl{" +
"userDao=" + userDao +
'}';
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public String find(){
return userDao.find();
}
}
xml :
<!--new UserDaoImpl()-->
<bean id="userDaoImpl" class="com.hz.dao.impl.UserDaoImpl">
<property name="aaa" value="1223444"/>
</bean>
<!--new UserServiceImpl()-->
<bean id="userServiceImpl" class="com.hz.service.impl.UserServiceImpl">
<!--new UserServiceImpl().setUserDao(new UserDaoImpl())-->
<property name="userDao" ref="userDaoImpl"/>
</bean>
构造函数注入(constructor-arg)
public HelloWorld() {}
public HelloWorld(String name, int age) {
this.name = name;
this.age = age;
}
<bean id="helloWorld" class="com.hz.pojo.HelloWorld">
<property name="name" value="张三"/>
<property name="age" value="24"/>
<!-- <constructor-arg><ref bean="userDao" /> -->
<constructor-arg name="name" value="111"/>
<constructor-arg name="age" value="12"/>
</bean>
p命名空间注入属性值
xmlns:p="http://www.springframework.org/schema/p"
<!--对于直接量(基本数据类型、字符串)属性:p:属性名="属性值"-->
<bean id="helloWorld" p:name="李四" p:age="123" class="com.hz.pojo.HelloWorld"/>
<!--对于引用Bean的属性:p:属性名-ref="Bean的id"-->
<bean id="userService" class="service.impl.UserServiceImpl" p:dao-ref="userDao" />
注入数组,字符串,集合…各种类型
public class TestEntity {
private String specialCharacter1; // 特殊字符值1
private String specialCharacter2; // 特殊字符值2
private User innerBean; // JavaBean类型
private List<String> list; // List类型
private String[] array; // 数组类型
private Set<String> set; // Set类型
private Map<String, String> map; // Map类型
private Properties aaa; // Properties类型
private String emptyValue; // 注入空字符串值
private String nullValue; // 注入null值
}
<bean id="testEntity" class="com.hz.pojo.TestEntity">
<property name="specialCharacter1">
<value>
<![CDATA[ P&G ]]>
</value>
</property>
<property name="specialCharacter2">
<value>P&G</value>
</property>
<property name="emptyValue">
<value></value>
</property>
<property name="nullValue">
<null></null>
</property>
<property name="aaa">
<props>
<prop key="aa">张三</prop>
<prop key="bb">张三111</prop>
</props>
</property>
<property name="list">
<list>
<value>1111</value>
<value>22</value>
<value>333</value>
</list>
</property>
<property name="array">
<array>
<value>1111</value>
<value>22</value>
<value>333</value>
</array>
</property>
<property name="set">
<set>
<value>1111</value>
<value>22</value>
<value>333</value>
</set>
</property>
<property name="map">
<map>
<entry>
<key>
<value>abc</value>
</key>
<value>12345</value>
</entry>
<entry>
<key>
<value>cba</value>
</key>
<value>456767</value>
</entry>
</map>
</property>
<property name="innerBean">
<bean class="com.hz.pojo.User">
<property name="username">
<value>花花</value>
</property>
</bean>
</property>
</bean>
2.3 Spring IOC常用注解
@Component:pojo entrty utils config(公共类)
@Repository:Dao层实现类
@Service:service 层实现类
@Controller:控制器层 Controller类
//JAVA EE的注解
//@WebServlet servlet类注解
//@Resource(name="")(先按名称,再按类型)==@Qualifier+@Autowired
@Qualifier(name="") (按名称注入)
@Autowired (按数据类型注入)
@Component
<!--<bean id="user" class="com.hz.pojo.User"/>-->
@Component(value = "user")
public class User {
}
@Repository
// <!--<bean id="userDaoImpl" class="com.hz.dao.impl.UserDaoImpl">-->
@Repository(value = "userDaoImpl")
public class UserDaoImpl implements UserDao {}
@Service
@Service(value = "userServiceImpl")
public class UserServiceImpl implements UserService {}
@Autowired+@Qualifier(value = "user")= @Resource(name = "user")
public class UserDaoImpl implements UserDao {
//javaee 默认按照名称匹配
//@Resource(name = "user") <!--<property name="user" ref="user"/>-->
@Autowired()//按照数据类型匹配
@Qualifier(value = "user")
private User user;
}
开启注解
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
;
<!-- 开启dao,pojo,service层注解-->
<context:component-scan base-package="com.hz.pojo,com.hz.dao,com.hz.service"/>
3. AOP
AOP 即 Aspect Oriented Program 面向切面编程(公共功能集中解决)
所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情况下给程序动态添加功能的技术
AOP相关术语:
增强处理(Advice)
- 前置增强
- 后置增强
- 环绕增强、异常抛出增强、最终增强等类型
切入点(Pointcut)
连接点(Join Point)
切面(Aspect)
目标对象(Target object)
AOP代理(AOP proxy)
织入(Weaving)
//给该方法做增强(切入点)
public int aa() {
return userDao.aa();
}
//增强类(AOP代理)
public class AopLog {
//前置增强方法
public void beforeLog(){
System.out.println("前置增强.....");
}
//后置前置增强方法
public void afterLog(Object res){
System.out.println("后置增强....."+"返回值:"+res);
}
}
导入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.7</version>
</dependency>
<!-- 头部信息-->
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
<bean id="aopLog" class="com.hz.utils.AopLog"/>
<aop:config>
<!--定义切入点-->
<aop:pointcut id="Log" expression="execution(* com.hz.service..*.*(..))"/>
<!--织入增强处理-->
<aop:aspect ref="aopLog">
<!--使用前置增强,将切入点与beforeLog方法绑定-->
<aop:before method="beforeLog" pointcut-ref="Log"/>
<!--使用后置增强,将切入点与afterLog方法绑定 returning 返回参数接收-->
<aop:after-returning method="afterLog" pointcut-ref="Log" returning="res"/>
</aop:aspect>
</aop:config>
//目标对象
@Test
public void aa() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService=(UserService)applicationContext.getBean("userServiceImpl");
userService.aa();
}
3.1 五种增强方式
目录 | 说明 | 使用 |
---|---|---|
前置增强 | 在一个方法执行之前,执行通知 | before |
后置增强 | 在一个方法执行之后,只有在方法成功完成时,才能执行通知 | after-returning |
最终增强 | 在一个方法执行之后,不考虑结果,执行通知 | after |
异常增强 | 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知 | after-throwing |
环绕增强 | 在一个方法执行之后,执行通知 | around |
3.2 AOP注解
开启注解
<aop:aspectj-autoproxy/>
@Component
@Aspect //<aop:aspect ref="AopLog">
public class AopLog {
@Pointcut("execution(* com.hz.service..*.*(..))")
public void pointcut(){}
@Before("pointcut()")
public void beforeLog(){
System.out.println("前置增强.....");
}
@AfterReturning(value = "pointcut()",returning = "res")
public void afterReturningLog(Object res){
System.out.println("后置增强....."+"返回值:"+res);
}
@After("pointcut()")
public void afterLog(){
System.out.println("最终增强.....");
}
@AfterThrowing(value = "pointcut()",throwing = "e")
public void afterThrowing(RuntimeException e){
System.out.println("异常增强..."+e);
}
}
@Aspect
@Component(value="loggerSpringAop")
public class LoggerSpringAop {
//把自己创建的类当作原生Logger类,目的对原生类的方法改造
private static Logger log=Logger.getLogger(String.valueOf(LoggerSpringAop.class));
// execution(public void findUser()) 起别名 叫 a()
@Pointcut(value = "execution(* com.hz.service..*.*(..))")
public void a(){}
//前置增强(在目标方法之前运行)
//<aop:before method="before" pointcut-ref="aa"/>
//@Before(value = "execution(public void findUser())")
@Before(value = "a()")
public void before(JoinPoint jp) {
log.info("before()"+"调用 " + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
//后置增强(在目标方法之后运行)
//<aop:after-returning method="afterReturning" pointcut-ref="aa" returning="result"/>
//@AfterReturning(value = "execution(public void findUser())",returning = "result")
@AfterReturning(value = "a()",returning = "result")
public void afterReturning(JoinPoint jp, Object result) {
log.info("afterReturning()"+"调用" + jp.getTarget() + " 的 " + jp.getSignature().
getName() + " 方法。方法返回值:" + result);
}
}