1,spring核心
spring的核心是控制反转(IOC),和面向切向(AOP)
2,spring优点
(1)方便解耦,简化开发 (高内聚低耦合)
• Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理
• spring工厂是用于生成bean
(2)AOP编程的支持
• Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能 (日记)
(3)声明式事务的支持
• 只需要通过配置就可以完成对事务的管理,而无需手动编程
(4)方便程序的测试
• Spring对Junit4支持,可以通过注解方便的测试Spring程序
(5)方便集成各种优秀框架
• Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
(6)降低JavaEE API的使用难度
• Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低
3,spring分层: 一站式,每一个层都提供的解决方案
web层:struts,spring-MVC
service层:spring
dao层:hibernate,mybatis , jdbcTemplate --> spring-data
4,spring体系结构
5,入门案例(IOC)
1,导入jar包
(1)4 + 1 : 4个核心(beans、core、context、expression) + 1个依赖(commons-loggins…jar)
(2)位置
4核心:\spring-framework-3.2.0.RELEASE-dist\libs
1依赖
spring-framework-3.0.2.RELEASE-dependencies
\org.apache.commons\com.springsource.org.apache.commons.logging\
(3)示例
拷贝到WEB-INF下的lib文件夹下
2,添加约束
(1)位置:任意,开发中一般在classpath下(src)
(2)名称:任意,开发中常用applicationContext.xml
(3)内容:添加schema约束
(4)约束文件位置:spring-framework-3.2.0.RELEASE\docs\spring-framework-reference\html\ xsd-config.html
(5)示例:
配置xml
注:ClassPathXmlApplicationContext路径下有时加项目名,有时不加
3,依赖注入
(1)配置applicationContext.xml
(2)通过setter注入实现private UserDao userDao=new UserDaoImpl();
public class UserServiceImpl implements UserService {
// private UserDao userDao=new UserDaoImpl();
private UserDao userDao;
//spring开发,通过setter注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void SaveUser() {
userDao.sava();
}
}
(3)Test() 方法执行
public class TestUserService {
@Test
public void test02(){
//applicationContext路径/SpringDay01/src/com/xl/b_id/applicationContext.xml
String applicationContext="com/xl/b_id/applicationContext.xml";
//1,获取spring容器,ApplicationContext来自spring-context-3.2.0.RELEASE.jar
ApplicationContext ac=new ClassPathXmlApplicationContext(applicationContext);
//2,通过spring获取对象,对象即.xml中对应的id
//方法一,通过UserService强转
//UserService userService=(UserService) ac.getBean("UserService");
//方法二,
UserService userService=ac.getBean("UserService",UserService.class);
userService.SaveUser();
}
}
4,myeclipse schema xml提示
步骤一:确定xsd文件位置
spring-framework-3.2.0.RELEASE-dist\schema\beans
步骤二:复制路径
步骤三:搜索“xml catalog”
步骤四:添加约束提示
6,基于XML装配bean
6.1实例化方式
3种bean实例化方式:默认构造、静态工厂、实例工厂
(1)默认构造
<bean id="" class=""> //必须提供默认构造无参的构造方法
(2)静态工厂
常用与spring整合其他框架(工具)
静态工厂:用于生成实例对象,所有的方法必须是static
<bean id="" class="工厂全限定类名" factory-method="静态方法">
示例:
(3)实例工厂
6.2作用域
(1)单例
配置xml;
测试
输出结果:
(2)多例
配置xml
测试:
运行结果:
6.3生命周期
public class UserServiceImpl implements UserService {
public void SaveUser() {
System.out.println("init_destory");
}
//初始化
public void Myinit(){
System.out.println("初始化成功");
}
//销毁
public void Mydestory(){
System.out.println("销毁成功");
}
}
<!--1, 创建实例工厂 class:类名 factory-method:该类中的方法-->
<!--init-method:初始化
destroy-method:销毁-->
<bean id="UserServiceId" class="com.xl.f_init_destory.UserServiceImpl"
init-method="Myinit" destroy-method="Mydestory"></bean>
package com.xl.f_init_destory;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestInitDestory {
@Test
public void test02() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(
"/com/xl/f_init_destory/applicationContext.xml");
UserService userService1 = (UserService) ac.getBean("UserServiceId");
userService1.SaveUser();
ac.destroy();
}
}
运行结果:
注:多例不能销毁
当在bean中加上scope="prototype
6.4属性依赖注入
依赖注入方式:手动装配 和 自动装配
(1)手动装配:一般进行配置信息都采用手动
基于xml装配:构造方法、setter方法、接口注入(spring不支持)
基于注解装配:
(2)自动装配:struts和spring 整合可以自动装配
byType:按类型装配
byName:按名称装配
constructor构造装配,
auto: 不确定装配。
(3)通过setter方法注入
创建对象实体:
public class User {
private int id;
private String name;
private List lists;
private String[] sts;
private Map map;
private UserVo userVo;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getLists() {
return lists;
}
public void setLists(List lists) {
this.lists = lists;
}
public String[] getSts() {
return sts;
}
public void setSts(String[] sts) {
this.sts = sts;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
public UserVo getUserVo() {
return userVo;
}
public void setUserVo(UserVo userVo) {
this.userVo = userVo;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", lists=" + lists
+ ", sts=" + Arrays.toString(sts) + ", map=" + map
+ ", userVo=" + userVo + "]";
}
}
public class UserVo {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "UserVo [id=" + id + ", name=" + name + "]";
}
}
配置xml
<bean id="UserId" class="com.xl.g.setter.User">
<!-- 普通属性注入 -->
<property name="id" value="123"></property>
<property name="name">
<value>小明</value>
</property>
<!-- 集合数组可以互相替换,可以用value也可以用list -->
<!-- 集合注入 -->
<property name="lists">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<!-- 数组注入 -->
<property name="sts">
<array>
<value>s1</value>
<value>s2</value>
<value>s3</value>
</array>
</property>
<!-- map注入,是通过键值对key value -->
<property name="map">
<map>
<entry key="1" value="www"></entry>
<entry key="2" value="aaa"></entry>
</map>
</property>
<!-- 注入对象 -->
<property name="userVo" ref="UserVoId">
</property>
</bean>
<!-- 创建UserVo对象 -->
<bean id="UserVoId" class="com.xl.g.setter.UserVo">
<property name="id" value="123"></property>
<property name="name" value="大魔王"></property>
</bean>
测试类:
public class TestSetter {
@Test
public void test02(){
//获得spring容器
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(
"/com/xl/g/setter/beans.xml");
//通过spring容器获得对象
User user=(User)ac.getBean("UserId");
System.out.println(user);
}
}
运行结果:
(4)通过构造方法注入
spring默认通过无参构造方法注入
流程
(1)测试类
(2)bean.xml
(3)User类
通过有参构造方法注入
<?xml version="1.0" encoding="UTF-8"?>
<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">
<bean id="UserId" class="com.xl.h_con.User">
<!-- 通过构造方法注入 -->
<!-- 1,普通属性-->
<!-- index:代表构造方法中的第几个属性默认从零开始,也可以用name+构造属性名称 -->
<constructor-arg index="0" value="123"></constructor-arg>
<constructor-arg name="name" value="徐大林"></constructor-arg>
<!-- 等同于
<constructor-arg name="name" >value="徐大林"</constructor-arg>
-->
<!-- 2,list -->
<constructor-arg index="2">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</constructor-arg>
<!-- 3,数组 -->
<constructor-arg name="sts">
<array>
<value>ar1</value>
<value>ar2</value>
<value>ar3</value>
</array>
</constructor-arg>
<!--4,map -->
<constructor-arg name="map">
<map>
<entry key="dg" value="东莞"></entry>
</map>
</constructor-arg>
</bean>
</beans>
package com.xl.h_con;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class User {
private int id;
private String name;
private List lists;
private String[] sts;
private Map map;
public User(int id, String name, List lists, String[] sts, Map map) {
super();
this.id = id;
this.name = name;
this.lists = lists;
this.sts = sts;
this.map = map;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", lists=" + lists
+ ", sts=" + Arrays.toString(sts) + ", map=" + map + "]";
}
}
7,基于注解装配bean
1,以@Component注解为例
1,在xml中修改约束
将123处修改后添加
将
xmlns="http://www.springframework.org/schema/beans"
改为:
xmlns context="http://www.springframework.org/schema/context"
添加;
将
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
改为:
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
添加:
结果为:
2,扫描装配bean,即扫描那个包下面的
3,在UserServiceImpl类加注解
4,执行测试类即可;
5,全部代码
(1)UserServiceImpl类
package com.xl.a_annotation;
import org.springframework.stereotype.Component;
@Component("userServiceId")
public class UserServiceImpl implements UserService {
public void saveUser() {
System.out.println("saveUser");
}
}
(2)xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<!-- 扫描装备bean -->
<context:component-scan base-package="com.xl.a_annotation"></context:component-scan>
</beans>
(3)测试类
package com.xl.a_annotation;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="com/xl/a_annotation/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象
UserService userService=(UserService)ac.getBean("userServiceId");
userService.saveUser();
}
}
6,逻辑
通过Test中的1找到对应的xml文件,通过xml文件中的3找到包com.xl.a_annotation,
通过测试类中的2,找到com.xl.a_annotation包下的UserServiceImpl类
注
在添加注释时@Component(“userServiceId”)也可以写成@Component
此时对应的Test类需要改写为:
UserService userService=(UserService)ac.getBean("userServiceImpl");
//userServiceImpl 为UserServiceImpl类中类首字母小写。
//通过userServiceImpl找到UserServiceImpl类
2,自定义注解
1,4个原注解
(1)@Target
@Target(ElementType.FIELD)声明注解作用在属性上
@Target(ElementType.METHOD)声明注解作用在方法上
@Target(ElementType.TYPE)声明注解作用类,或者接口中
@Target({ElementType.TYPE,ElementType.METHOD,
ElementType.FIELD,})可以配置多个
(2)@Retention
@Retention(RetentionPolicy.SOURCE):注解只保留在原文件,当编译程class文件的时候,注解就被遗弃。
@Retention(RetentionPolicy.CLASS):注解保留到class文件,但jvm加载class文件之后,注解就被遗弃。
@Retention(RetentionPolicy.RUNTIME):注解不仅被保留到class文件中,jvm加载class之后,仍然存在。
(3)@Documented 生成javadoc时,注解会生成相关文档
(4)@Inheritance代表注解可以被子类继承
2,以JDBC为例
(1)定义注释
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JDBCConfig {
public String url();
public String user();
public String password();
}
(2)引用注释
@JDBCConfig(url="jdbc:oracle:thin:@127.0.0.1:1521:XE",user="xiaoming",password="123456")
public class DBUtil {
static{
try {
Class.forName("oracle.jdbc.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn = null;
//通过反射
JDBCConfig jdbcConfig = DBUtil.class.getAnnotation(JDBCConfig.class);
String url = jdbcConfig.url();
String user = jdbcConfig.user();
String password = jdbcConfig.password();
System.out.println(url);
return conn;
}
public static void main(String[] args) {
System.out.println(DBUtil.getConnection());
}
}
3,@Component引申的注解
1,@Repository:dao层
@Service:业务层
@Controller:控制层
2,例:以jdbk为例
(1)常规方法:
测试类
package com.xl.d_web;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="com/xl/d_web/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象
UserAction userAction=(UserAction)ac.getBean("userAction");
userAction.saveUser();
}
}
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<!-- 扫描装备bean -->
<context:component-scan base-package="com.xl.d_web"></context:component-scan>
</beans>
UserAction类
package com.xl.d_web;
import org.springframework.stereotype.Component;
//也可以用@Component,userAction与首字母小写与UserAction对应
@Component("userAction")
public class UserAction {
UserService userService=new UserServiceImpl();
public void saveUser(){
userService.saveUser();
}
}
UserServiceImpl类
package com.xl.d_web;
public class UserServiceImpl implements UserService {
UserDao userDao=new UserDaoImpl();
public void saveUser() {
userDao.saveUser();
}
}
UserDaoImpl类
package com.xl.d_web;
public class UserDaoImpl implements UserDao {
public void saveUser(){
System.out.println("UserDaoImpl方法");
};
}
运行结果:
逻辑
(2)通过注释方法:
使用@Resource
个人理解: @Resource与@Service(“userService”)等一一对应
测试类TestDemo
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="com/xl/d_web/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象,userAction与首字母小写与UserAction对应
UserAction userAction=(UserAction)ac.getBean("userAction");
userAction.saveUser();
}
}
xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<!-- 扫描装备bean -->
<context:component-scan base-package="com.xl.d_web"></context:component-scan>
</beans>
控制层UserAction
package com.xl.d_web;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
//@Component也行
@Controller
public class UserAction {
@Resource
UserServiceImpl userService;
public void saveUser(){
userService.saveUser();
}
}
业务层UserServiceImpl
package com.xl.d_web;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
//@Component("userService")也行
@Service("userService")
public class UserServiceImpl implements UserService {
@Resource
UserDao userDao;
public void saveUser() {
userDao.saveUser();
}
}
Dao层UserDaoImpl
package com.xl.d_web;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
//@Component("userDao")也行
@Service("userDao")
public class UserDaoImpl implements UserDao {
public void saveUser(){
System.out.println("UserDaoImpl方法");
};
}
使用 @Autowired
只需要用@Autowired换掉@Resource即可
花里胡哨,没弄懂
8,AOP
一:定义:
1, 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP(面向对象编程)的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2,AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
3,经典应用:事务管理、性能监视、安全检查、缓存 、日志等
4,Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码
5,AspectJ是一个基于Java语言的AOP框架,Spring2.0开始,Spring AOP引入对Aspect的支持,AspectJ扩展了Java语言,提供了一个专门的编译器,在编译时提供横向代码的织入
二:AOP实现原理
1,aop底层将采用代理机制进行实现。
2,接口 + 实现类 :spring采用 jdk 的动态代理Proxy。
3,实现类:spring 采用 cglib字节码增强。
三:jdk 的动态代理基本方法及属性
代理 :目标类+切面类 形成集合即AOP切面
3.1参数1:loader,类加载器,动态代理类 运行时创建
3.2参数2:interfaces,代理类需要实现的所有接口
方式1:userService.getClass().getInterfaces();//一个接口
方式2:new Class[]{userService.getClass().getInterfaces()};//多个接口
3.3参数3:InvocationHandler(),处理类,接口,必须进行实现,
Object proxy:代理对象
Method method:
method.invoke(obj, args):每个方法都会调用一次
method.getName():获取方法名
Object[] args:方法当中的一些参数
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(), //加载MyBeanFactory类
userService.getClass().getInterfaces(),//代理类所需要实现的接口
new InvocationHandler() { //处理类接口
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 1,执行前
myAspace.before();
// 2,执行目标方法 userService
Object obj = method.invoke(userService, args);
System.out.println(method.getName());
// 3,执行后
myAspace.after();
return obj;
}
})
示例
测试类:
package f_jdk;
public class TestDemo {
public static void main(String[] args) {
UserService userService=MyBeanFactory.CreatUserService();
userService.saveUser();
userService.deleteUser();
userService.updateUser();
}
}
静态工厂
package f_jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
* 工厂
* */
public class MyBeanFactory {
public static UserService CreatUserService() {
// 1,目标类,必须加final
final UserService userService = new UserServiceImpl();
// 2,切面类,必须加final
final MyAspace myAspace = new MyAspace();
// 3,
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(), userService.getClass()
.getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 1,执行前
myAspace.before();
// 2,执行目标方法 userService
Object obj = method.invoke(userService, args);
System.out.println(method.getName());
// 3,执行后
myAspace.after();
return obj;
}
});
return userServiceProxy;
}
}
切面类
package f_jdk;
/*
* 切面类:充当代理人
* */
public class MyAspace {
public void before(){
System.out.println("执行前");
}
public void after(){
System.out.println("执行后");
}
}
UserServiceImpl类
package f_jdk;
public class UserServiceImpl implements UserService {
public void saveUser() {
System.out.println("f_jdk save");
}
public void updateUser() {
System.out.println("f_jdk update");
}
public void deleteUser() {
System.out.println("f_jdk delete");
}
}
UserService接口
package f_jdk;
public interface UserService {
public void saveUser();
public void updateUser();
public void deleteUser();
}
执行结果:
四:cglib字节码增强
1,没有接口,只有实现类。
2,采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
/*
* 工厂
* */
public class MyBeanFactory {
public static UserService createUserService(){
//1.目标类
final UserService userService = new UserServiceImpl();
//2.切面类
final MyAspace myAspect = new MyAspace();
// 3.代理类 ,采用cglib,底层创建目标类的子类
//3.1 核心类
Enhancer enhancer = new Enhancer();
//3.2 确定父类
enhancer.setSuperclass(userService.getClass());
/* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
* intercept() 等效 jdk invoke()
* 参数1、参数2、参数3:以invoke一样
* 参数4:methodProxy 方法的代理
*
*
*/
enhancer.setCallback(new MethodInterceptor(){
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//前
myAspect.before();
//执行目标类的方法
Object obj = method.invoke(userService, args);
// * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
//methodProxy.invokeSuper(proxy, args);
//后
myAspect.after();
return obj;
}
public Object intercept1(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
return null;
}
});
//3.4 创建代理
UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
return proxService;
}
}
五,Spring编写:半自动
让spring创建代理对象,从spring手动获取代理对象
项目流程
导入jar包(四个核心+一个依赖+spring apo+ 实现aop联盟)
四个核心
\spring-framework-3.2.0.RELEASE-dist\spring-framework-3.2.0.RELEASE\libs
一个依赖
spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1
spring apo 实现
spring-framework-3.2.0.RELEASE-dist\spring-framework-3.2.0.RELEASE\libs
aop联盟
spring-framework-3.0.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0
所有jar包
UserService类
public interface UserService {
public void addUser();
public void updateUser();
public void deleteUser();
}
UserServiceImpl类
public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("addUser");
}
public void updateUser() {
System.out.println("updateUser");
}
public void deleteUser() {
System.out.println("deleteUser");
}
}
MyAspect类
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/*
* 切面中确定通知,采用的是环绕通知即MethodInterceptor
* MethodInterceptor
* */
public class MyAspect implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
//1
System.out.println("执行前");
//2,执行目标方法
Object object=mi.proceed();
//3
System.out.println("执行后");
return object;
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1,确定目标类 -->
<bean id="UserServiceImplId" class="UserServiceImpl"></bean>
<!-- 2,确定切面类 -->
<bean id="MyAspectId" class="MyAspect"></bean>
<!-- 3,创建代理-->
<!-- 创建代理类ProxyFactoryBean 用于创建代理工厂bean -->
<bean id="UserServiceProxyId" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 确定接口们 多个接口 用<array></array> 一个接口用value-->
<property name="interfaces" value="UserService"></property>
<!-- 确定目标类 -->
<property name="target" ref="UserServiceImplId"></property>
<!-- 通知切面类的名称 多个接口 用<array></array> 一个接口用value-->
<property name="interceptorNames" value="MyAspectId"></property>
<!-- optimize=true的情况下,强制使用cglib -->
<!--<property name="optimize" value="true"></property> -->
</bean>
</beans>
TestDemo类
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象
// UserService userService=(UserService)ac.getBean("UserServiceImplId");
UserService userService=(UserService)ac.getBean("UserServiceProxyId");
userService.addUser();
userService.deleteUser();
userService.updateUser();
}
}
运行结果:
六,Spring编写:全自动
在半自动基础上导入jar包
路径:spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
更改apo信息
示例一:一个通知,一个切入类
特殊的切面,只有一个通知和一个切入类
pointcut="":切入点
execution(返回值 包.类名.方法名)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1,确定目标类 -->
<bean id="UserServiceImplId" class="b_aop.UserServiceImpl"></bean>
<!-- 2,确定切面类 -->
<bean id="MyAspectId" class="b_aop.MyAspect"></bean>
<!-- APO全自动
proxy-target-class="true":声明使用cglib代理
-->
<aop:config proxy-target-class="true">
<aop:advisor advice-ref="MyAspectId" pointcut="execution(void b_aop.UserServiceImpl.addUser())"/>
</aop:config>
结果:
示例二:一个通知,多个切入类
用*代表所有,用(…)代表任意参数
<aop:advisor advice-ref="MyAspectId" pointcut="execution(* b_aop.*.*(..))"/>
运行结果:
9,AspectJ
一,介绍
1, AspectJ是一个基于Java语言的AOP框架
2, Spring2.0以后新增了对AspectJ切点表达式支持
3,@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP
4,主要用途:自定义开发
二,切入点表达式
execution() 用于描述方法
语法:execution(修饰符 返回值 包.类.方法名(参数) throws异常)
1,修饰符,一般省略
public //公共方法
* //任意
2,返回值,不能省略
void //返回没有值
String //返回值字符串
* //任意
3,包,[省略]
crm //固定包
crm.*.service //crm包下面子包任意 (例如:crm.staff.service)
crm.. //crm包下面的所有子包(含自己)
crm.*.service.. //crm包下面任意子包,固定目录service,service目录任意包
4,类,[省略]
UserServiceImpl //指定类
*Impl //以Impl结尾
User* //以User开头
* //任意
5,方法名,不能省略
addUser //固定方法
add* //以add开头
*Do //以Do结尾
* //任意
6, (参数)
() 无参
(int) 一个整型
(int ,int) 两个
(..) 参数任意
7,throws ,可省略,一般不写。
综合1
execution(* com.*.service.*.*(..))
综合2
execution(* com.模块名.service*.*(..))
三,AspectJ通知类型
1, aop联盟定义通知类型,具有特性接口,必须实现,从而确定方法名称。
2,aspectj 通知类型,只定义类型名称。已经方法格式。
3,个数:6种,会用5种,了解1种。
(1)before:前置通知(应用:各种校验)
在方法执行前执行,如果通知抛出异常,阻止方法运行
(2)afterReturning:后置通知(应用:常规数据处理)
方法正常返回后执行,如果方法中抛出异常,通知无法执行
必须在方法执行后才执行,所以可以获得方法的返回值。
(3)around:环绕通知(应用:十分强大,可以做任何事情)
方法执行前后分别执行,可以阻止方法的执行
必须手动执行目标方法
(4)afterThrowing:抛出异常通知(应用:包装异常信息)
方法抛出异常后执行,如果方法没有抛出异常,无法执行
(5)after:最终通知(应用:清理现场)
方法执行完毕后执行,无论方法中是否出现异常
三,基于xml写AspectJ
导入jar包
示例:
UserService接口
package c_xml;
public interface UserService {
public void addUser();
public String updateUser();
public void deleteUser();
}
UserServiceImpl类
package c_xml;
public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("addUser");
}
public String updateUser() {
System.out.println("updateUser");
return "返回值";
}
public void deleteUser() {
System.out.println("deleteUser");
}
}
MyAspect类
package c_xml;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/*
* 切面类含有多个通知
* */
public class MyAspect {
/*
* 前置通知
* */
public void myBefore(JoinPoint joinPoint){//JoinPoint 连接点
System.out.println("前置通知-方法名为:"+joinPoint.getSignature().getName());
}
/*
* 后置通知
* */
public void myAfterReturning(JoinPoint joinPoint, Object obj){
System.out.println("后置通知-方法名为:"+joinPoint.getSignature().getName()+"返回值是"+obj);
}
/*
* 环绕通知
* */
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("执行前");
//执行目标方法
Object object=joinPoint.proceed();
System.out.println("执行后");
return object;
}
/*
* 异常通知
* */
public void myAfterThrowing(JoinPoint joinPoint, Throwable e){
System.out.println("异常通知"+e.getMessage());
}
/*
* 最终通知,不管什么情况下都会执行的方法
* */
public void myAfter(JoinPoint joinPoint){
System.out.println("最终通知");
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 1,确定目标类 -->
<bean id="UserServiceImplId" class="c_xml.UserServiceImpl"></bean>
<!-- 2,确定切面类 -->
<bean id="MyAspectId" class="c_xml.MyAspect"></bean>
<!-- 3,APO-->
<aop:config>
<!-- 基于框架,确定切面类 -->
<aop:aspect ref="MyAspectId">
<!-- 定义公共的切入点 -->
<aop:pointcut expression="execution(* c_xml.*.*(..))" id="mypointcut"/>
<!-- 配置前置通知,method确定方法 pointcut确定切入点-->
<aop:before method="myBefore" pointcut-ref="mypointcut"/>
<!-- 配置后置通知 returning="obj":返回值,obj需要和MyAspect类中的obj对应-->
<aop:after-returning method="myAfterReturning" pointcut-ref="mypointcut" returning="obj"/>
<!-- 配置环绕通知 -->
<aop:around method="myAround" pointcut-ref="mypointcut"/>
<!-- 配置异常通知 -->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="mypointcut" throwing="e"/>
<!-- 配置最终通知 -->
<aop:after method="myAfter" pointcut-ref="mypointcut"/>
</aop:aspect>
</aop:config>
</beans>
TestDemo 类
package c_xml;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="/c_xml/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象
// UserService userService=(UserService)ac.getBean("UserServiceImplId");
UserService userService=(UserService)ac.getBean("UserServiceImplId");
userService.addUser();
userService.deleteUser();
userService.updateUser();
}
}
执行结果:
四,基于注解写AspectJ
示例:
UserService接口
package com.xl.d_annotation;
public interface UserService {
public void addUser();
public String updateUser();
public void deleteUser();
}
UserServiceImpl类
package com.xl.d_annotation;
import org.springframework.stereotype.Component;
@Component
public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("addUser");
}
public String updateUser() {
System.out.println("updateUser");
return "返回值";
}
public void deleteUser() {
System.out.println("deleteUser");
}
}
MyAspect类
package com.xl.d_annotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/*
* 切面类含有多个通知
* */
@Component
@Aspect
public class MyAspect {
/*
* 声明一个公共切入点
*/
@Pointcut("execution(* com.xl.d_annotation.*.*(..))")
public void myPointCut() {
}
/*
* 前置通知
*/
@Before(value = "myPointCut()")
public void myBefore(JoinPoint joinPoint) {// JoinPoint 连接点
System.out.println("前置通知-方法名为:" + joinPoint.getSignature().getName());
}
/*
* 后置通知
*/
@AfterReturning(value = "myPointCut()", returning = "obj")
public void myAfterReturning(JoinPoint joinPoint, Object obj) {
System.out.println("后置通知-方法名为:" + joinPoint.getSignature().getName()
+ "返回值是" + obj);
}
/*
* 环绕通知
*/
@Around(value = "myPointCut()")
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("执行前");
// 执行目标方法
Object object = joinPoint.proceed();
System.out.println("执行后");
return object;
}
/*
* 异常通知
*/
@AfterThrowing(value = "myPointCut()", throwing = "e")
public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("异常通知" + e.getMessage());
}
/*
* 最终通知,不管什么情况下都会执行的方法
*/
@After(value = "myPointCut()")
public void myAfter(JoinPoint joinPoint) {
System.out.println("最终通知");
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 扫描装配bean -->
<context:component-scan base-package="com.xl.d_annotation"></context:component-scan>
<!-- 确定aop注解生效 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
TestDemo类
package com.xl.d_annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="/com/xl/d_annotation/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象
// UserService userService=(UserService)ac.getBean("UserServiceImplId");
UserService userService=(UserService)ac.getBean("userServiceImpl");
userService.addUser();
userService.deleteUser();
userService.updateUser();
}
}
执行结果:
10,JdbcTemplate
spring 提供用于操作JDBC工具类,类似:DBUtils。
依赖 连接池DataSource (数据源)
示例:
导入jar包
示例一:数据池
package e_api;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class TestDemo {
public static void main(String[] args) {
//1,创建数据源(连接池)
BasicDataSource dataSource=new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mmsi");
dataSource.setUsername("root");
dataSource.setPassword("root");
System.out.println("数据库连接成功");
//2,创建模板
JdbcTemplate jdbcTemplate=new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
//3,通过api操作
jdbcTemplate.update("insert into t_user(username,password) values(?,?);", "tom","998");
System.out.println("数据库插入成功");
}
}
示例二:DBCP
UserDao 接口
package f_dbcp;
public interface UserDao {
public void update();
}
UserDaoImpl类
package f_dbcp;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class UserDaoImpl extends JdbcDaoSupport implements UserDao{
public void update(){
this.getJdbcTemplate().update(
"insert into t_user(username,password) values(?,?);", "adm","598");
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 创建数据源 -->
<bean id="dataSourceId" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mmsi"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 创建模板 ,需要注入数据源-->
<bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSourceId"></property>
</bean>
<!-- 配置dao -->
<bean id="userDaoId" class="f_dbcp.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplateId"></property>
</bean>
</beans>
TestDemo 类
package f_dbcp;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestDemo {
public static void main(String[] args) {
//1,获得spring容器
String beanPath="/f_dbcp/beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(beanPath);
//2,通过容器获得对象
UserDao userDao=ac.getBean("userDaoId",UserDao.class);
userDao.update();
System.out.println("数据库操作成功");
}
}
示例三:C3P0(1)
除了bean.xml,其他内容都一样
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 创建数据源 c3p0-->
<bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mmsi"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 创建模板 ,需要注入数据源-->
<bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSourceId"></property>
</bean>
<!-- 配置dao -->
<bean id="userDaoId" class="f_dbcp.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplateId"></property>
</bean>
</beans>
示例四:C3P0(2)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 创建数据源 c3p0-->
<bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mmsi"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 配置dao -->
<bean id="userDaoId" class="g_c3p0.UserDaoImpl">
<property name="dataSource" ref="dataSourceId"></property>
</bean>
</beans>
示例五:使用properties
(1)新建一个File:db.properties
(2)其他一样,配置bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:property-placeholder location="classpath:/g_c3p0/db.properties"/>
<!-- 创建数据源 c3p0-->
<bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置dao -->
<bean id="userDaoId" class="g_c3p0.UserDaoImpl">
<property name="dataSource" ref="dataSourceId"></property>
</bean>
</beans>
11,事务
导入jar包