ApplicationContext实现类
- ClassPathXmlApplicationContext:直接引用resources文件路径下的配置文件
- FileSystemXmlApplicationContext:文件磁盘地址
- AnnotationConfigApplicationContext
getBean
如果只有一个对象直接使用这个getBean(Class)
多个用getBean(“id”)需要强转
配置数据源
数据源提高性能
实例化数据源,初始化部分连接资源
使用连接资源从数据源中获取
使用完后归还给数据源
常见数据源 DBCP, C3P0,BoneCP,Druid
什么是数据源? 它可以被看做一个数据缓冲区 可以大大提升性能
数据库连接池的意义在于,能够重复利用数据库连接
配置C3P0
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
连接数据库读取数据
public void test1() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
dataSource.setUser("root");
dataSource.setPassword("111111");
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
连接数据库时 因为Server时区不同会报错需要在路径后加上serverTimezone=UTC
而这种方法让数据池与单一数据库过分耦合 非常不方便
使用配置文件加载使耦合变松
public void test3() throws Exception {
//读取配置文件
ResourceBundle rb = ResourceBundle.getBundle("jdbc"); //写resources下的内容的基名 只要写名字不用后缀,切路径名从resources开始
}
用命名空间导入properties文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context= "http://www.springframework.org/schema/context"
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" >
下面用spring注入以来 读取properties
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
注解开发
Spring轻代码而重配置,注解配置提高开发效率
@Component("userService")
public class UserServiceImpl implements UserService {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void save(){
userDao.save();
}
}
在用注解标明并生成实例以及内部依赖后要告诉Spring去扫描注释
<context:component-scan base-package="com.Qing"></context:component-scan>
如果使用XML配置 set方法要写
注解方式 set方法可以不写
Autowired 会按照数据类型从Spring容器中进行匹配,多个对象不适用
只有单个对象时可以不用Qualifier
Qualifier按照id值从容器中进行匹配的,但是此处必须使用Autowired
Resource = Autowired+Qualifier
问题:在Spring项目中引入@Resource注解的时候,有红色下划线错误,而且输入注解的时候不能出现自动代码补全。加入javax.annotation包后,出现警告。
解决办法:Spring项目中缺少javax.annotation包的依赖。在maven配置文件pom.xml中加入依赖。
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
Spring集成JUnit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:ApplicationContext.xml") //使用配置文件
@ContextConfiguration(classes = {SpringConfiguration.class}) //使用注解开发
动态代理
Java中的代理可以在不改变对象类的情况下对功能进行扩张,静态代理是指程序员手写代码完成代理
而动态代理则使用JDK中的proxy类来完成,具体例子如下
interface IDog{
void run();
}
//目标类
class GunDog implements IDog{
@Override
public void run() {
System.out.println("猎狗在跑");
}
}
class DogUtils{
public static void method1() {
System.out.println("增强方式一");
}
public static void method2() {
System.out.println("增强方式二");
}
}
class MyInvocationHandle implements InvocationHandler{
private Object target;
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
DogUtils.method1();
method.invoke(target, args);
DogUtils.method2();
return null;
}
}
//生产代理对象的工厂
class MyProxyFactory{
public static Object getProxy(Object target) {
MyInvocationHandle handle = new MyInvocationHandle();
handle.setTarget(target);
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle);
return proxy;
}
}
public class ProxyDemo {
public static void main(String[] args) {
IDog dog = new GunDog();
IDog proxy =(IDog) MyProxyFactory.getProxy(dog);
proxy.run();
}
}
Spring中的AOP就是动态代理,并且提供了简便的语法来配置
代理可以减少代码重复性:如果A有一个方法a(), B,C,D都要使用,这个时候不用在BCD类中都创建一个A对象再操作,而使用代理,可以直接引用这个代理,并使用该功能
使用AOP 动态结合,把目标方法与功能增强方法分开,使用配置文件,这样一个配置可以称为一个切面
分为JDK代理:基于接口的动态代理
与cglib代理:基于父类的动态代理
JDK代理:
public class ProxyTest {
public static void main(String[] args) {
final TargetInterface target = new Target();
//返回值就是动态生成的代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
//调用代理对象的任何方法 实质执行都是invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Advice.beforeSave();
method.invoke(target,args);
Advice.afterSave();
return null;
}
});
proxy.delete();
}
}
由于是基于接口的,只有接口中的方法才会有增强
基于cglib
public class ProxyTest {
public static void main(String[] args) {
final Target target = new Target();
//返回值 就是动态生成的代理对象 基于cglib
//创建增强器
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(Target.class);
//设置回调
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Advice.beforeSave();
methodProxy.invokeSuper(o,objects); //或者是Object invoke = method.invoke(target.objects)
Advice.afterSave();
return null;
}
});
//创建代理对象
Target proxy = (Target)enhancer.create();
proxy.save();
}
}
在cglib中
对于目标类(父类)中方法增强时,可以使用两种方法,一种是
methodProxy.invokeSuper(o,objects);
或者
Object invoke = method.invoke(target.objects)
都可以达到目标
可以被增强的方法就叫连接点